Je voulais savoir si la méthode {save}
dans CrudRepository
effectuait une mise à jour si elle trouvait déjà l'entrée dans la base de données comme:
@Repository
public interface ProjectDAO extends CrudRepository<Project, Integer> {}
@Service
public class ProjectServiceImpl {
@Autowired private ProjectDAO pDAO;
public void save(Project p) { pDAO.save(p); } }
Donc, si j'appelle cette méthode sur une entrée déjà enregistrée, elle sera mise à jour si elle trouve un attribut modifié?
Merci.
Je voulais savoir si la méthode {save} de CrudRepository effectuait une mise à jour s'il trouve déjà l'entrée dans la base de données
La documentation de Spring à ce sujet n'est pas précise:
Enregistre une entité donnée. Utilisez l'instance renvoyée pour d'autres opérations comme l'opération de sauvegarde peut avoir changé l'instance d'entité complètement.
Mais comme l'interface CrudRepository
ne propose pas une autre méthode avec un nom explicite pour la mise à jour d'une entité, on peut supposer que oui puisque CRUD doit effectuer toutes les opérations CRUD (CREATE, READ, UPDATE, DELETE).
Cette supposition est confirmée par l'implémentation de la SimpleJpaRepository
Class qui est l'implémentation par défaut de CrudRepository
qui montre que les deux cas sont traités par la méthode:
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Donc, si j'appelle cette méthode sur une entrée déjà enregistrée, elle sera mise à jour est-ce qu'il trouve un attribut modifié?
Dans ce cas, une opération de fusion sera effectuée. Tous les champs sont donc mis à jour en fonction de la définition des options de cascade et de lecture seule.
Regard sur l'implémentation par défaut de l'interface CrudRepository
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(Java.lang.Object)
*/
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Méthode Save gérer deux situations:
-Si l'identifiant de la personne est nul (une nouvelle entité est créée), alors save appellera la méthode persist = => la requête sera exécutée.
-Si l'identifiant de personne n'est pas null, alors save appellera la fusion: récupère l'entité existante dans entityManagerFactory (à partir du cache à 2 niveaux s'il n'existe pas, elle sera récupérée dans la base de données) Enfin, propagez les modifications dans la base de données en appelant la requête de mise à jour.
Je voulais savoir si la méthode {save} de CrudRepository effectue une mise à jour si elle trouve déjà l'entrée dans la base de données:
La réponse est oui, elle sera mise à jour si une entrée est trouvée:
De la documentation de printemps: ici https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html ?
L'enregistrement d'une entité peut être effectué via la méthode CrudRepository.save (…). Il persistera ou fusionnera l'entité donnée en utilisant le JPA EntityManager sous-jacent. Si l'entité n'a pas encore été conservée, Spring Data JPA l'enregistre via un appel à la méthode entityManager.persist (…), sinon la méthode entityManager.merge (…) est appelée.
Pour être plus précis, la méthode save (obj) traitera obj comme un nouveau record si le id est vide (donc fera un insert) et traitera obj comme un existant record si le id est rempli dans (donc fera la fusion).
Pourquoi est-ce important?
Supposons que l’objet Project contienne un identifiant généré automatiquement ainsi qu’un identifiant de personne qui doit être unique. Vous créez un objet Projet et remplissez le person_id mais pas l'id, puis essayez de sauvegarder. Hibernate essaiera d’insérer cet enregistrement car son identifiant est vide, mais si cette personne existe déjà dans la base de données, vous obtiendrez une exception de clé dupliquée.
Comment gérer
Soit faire un findByPersonId (id) pour vérifier si l’obj est déjà dans la base de données, et en obtenir l’identifiant s'il est trouvé,
Ou essayez simplement la sauvegarde et attrapez l’exception. Dans ce cas, vous savez que c’est déjà dans la base de données et que vous devez obtenir et définir l’id avant de sauvegarder.
Dans mon cas, j'ai dû ajouter la propriété id à l'entité et mettre l'annotation @Id comme ceci.
@Id
private String id;
Ainsi, lorsque vous obtenez l'objet, l'identifiant de l'entité se trouve dans la base de données et effectue l'opération de mise à jour à la place de la création.