Mon modèle est comme ça:
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name="email")
private String email;
@Column(name = "weblink")
private String webLink;
//getter & setter
}
nous collectons des données de formulaire ou mobiles via une requête http, et springmvc transmettra ces données à un utilisateur similaire à Model.
par exemple, j'ai une requête comme celle-ci:
http://localhost:8080/update?id=1919&[email protected]
dans contoller, l’URL de la requête et ses paramètres seront automatiquement transférés en un objet User
.
@RequestMapping(method = RequestMethod.GET, value = "/update0")
public User update(@ModelAttribute("User") User user){
System.out.println(user.getId());
System.out.println(user.getEmail());
System.out.println(user.getWebLink());
return userRepository.save(test);
}
si j'ai un enregistrement dans mysql dont l'id est 1919, et les colonnes (id, email, weblik) sont toutes des valeurs.
comme vous le voyez, l'objet utilisateur qui est passé par web ou mobile a deux propriétés
http://localhost:8080/update?id=1919&[email protected]
id et email ont des valeurs et weblink n'en ont pas.
Donc, si j'exécute la méthode save
, les colonnes email seront mises à jour à [email protected]
, et le champ weblik sera également mis à jour à NULL
, mais je ne veux pas mettre à jour ce champ, je veux simplement mettre à jour le champ email.
J'ai deux façons de résoudre le problème, mais toutes ne sont pas élégantes.
5.1 chargez d'abord l'objet utilisateur et mettez-le à jour
User userExist = userRepository.findOne(user.getId());
userExist.setEmail(user.getEmail());
//or using
//BeanUtil.copyProprty(formDto,modle)
userRepository.save();
5.2 en utilisant @DynamicUpdate
, mais cela ne fonctionne pas.
Existe-t-il un autre moyen de mettre à jour le modèle utilisateur sans effectuer de travail supplémentaire?.
Merci d'avance.
La méthode la plus simple consiste à configurer le contrôleur de manière appropriée:
@RequestMapping(value = "/users/{user}", method = RequestMethod.PATCH)
public … updateUser(@ModelAttribute User user) { … }
Selon la documentation de référence lorsque cette méthode est appelée, les étapes suivantes se produisent:
User
doit être obtenue. Cela nécessite en principe que Converter
de String
à User
soit enregistré auprès de Spring MVC pour convertir le segment de chemin extrait du modèle d'URI en User
. Si vous êtes par exemple en utilisant Spring Data et activez son support Web comme décrit dans sa documentation de référence , cela fonctionnera immédiatement.GET
comme méthode HTTP pour les mises à jour. GET
est défini comme une opération sûre (pas d'effets secondaires), contrairement à une mise à jour. PATCH
est la méthode correcte ici, telle qu'elle est définie pour autoriser les mises à jour partielles d'une ressource existante.PUT
et PATCH
, vous devez enregistrer un HttpPutFormContentFilter
avec l'application telle que décrite here . J'ai déposé un problème avec Spring Boot pour l'enregistrer par défaut.Au début, je dois dire que la solution Patch
de @Oliver Gierke
est vraiment géniale.
Et dans mon projet précédent, ma solution est:
1. Créez une classe abstraite pour implémenter JpaRepository
et la fonction save()
.
2. Dans la fonction de sauvegarde, obtenez l'entité à partir de la base de données. Cela n'existe pas, sauvegardez-le. Sinon, utilisez la réflexion pour extraire tous les champs NOT NULL de l'entité mise à jour et les définir dans l'entité à partir de la base de données. (il est similaire à ce que vous faites, mais je l'ai fait pour toutes les fonctions de sauvegarde)