J'utilise Spring Boot et hibernate over jpa. J'utilise l'interface JpaRepository pour implémenter mes référentiels. Comme avec UserRepository suivant
public interface UserRepository extends JpaRepository<User, Long> {
}
Je veux réussir à suivre
Toutes les étapes ci-dessus ne se produisent pas dans une transaction, c'est-à-dire que l'appel de service externe est hors transaction.
Lorsque j'enregistre le résultat de mon service Web dans DB via son référentiel, mes modifications dans l'entité utilisateur sont également enregistrées. Selon ma compréhension, cela est dû au vidage du contexte de persistance sous-jacent à l'étape # 3. Après quelques recherches sur Google, je pense que je peux atteindre mon objectif, si je peux détacher mon entité utilisateur à la première étape et la rattacher à l'étape 4. Veuillez confirmer si ma compréhension est correcte et comment y parvenir? Il n'y a pas de méthode dans l'interface JpaRepository pour détacher une entité.
Voici le code pour illustrer
public void updateUser(int id, String name, int changeReqId){
User mUser = userRepository.findOne(id); //1
mUser.setName(name); //2
ChangeRequest cr = changeRequestRepository.findOne(changeReqId);
ChangeResponse rs = userWebService.updateDetails(mUser); //3
if(rs.isAccepted()){
userRepository.saveAndFlush(mUser); //4
}
cr.setResponseCode(rs.getCode());
changeRequestRepository.saveAndFlush(cr); //this call also saves the changes at step 2
}
Merci
Si vous utilisez JPA 2.0, vous pouvez utiliser EntityManager # detach () pour détacher une seule entité du contexte de persistance. De plus, Hibernate a un Session # evict () qui sert le même but.
Puisque JpaRepository
ne fournit pas cette fonctionnalité elle-même, vous pouvez ajouter une implémentation personnalisée , quelque chose comme ceci
public interface UserRepositoryCustom {
...
void detachUser(User u);
...
}
public interface UserRepository extends JpaRepository<User, Long>, UserRepositoryCustom {
...
}
@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
...
@PersistenceContext
private EntityManager entityManager;
@Override
public void detachUser(User u) {
entityManager.detach(u);
}
...
}
Je n'ai pas essayé ce code, mais vous devriez pouvoir le faire fonctionner. Vous pouvez même essayer d'obtenir une prise sur EntityManager
dans votre classe de service (où updateUser()
est) avec @PersistenceContext
, Et éviter l'effort d'ajouter une implémentation personnalisée au référentiel.
entityManager.clear()
déconnectera tous les objets JPA, ce qui pourrait ne pas être une solution appropriée dans tous les cas, si vous avez d'autres objets que vous prévoyez de garder connectés.
clair
/**
* Clear the persistence context, causing all managed
* entities to become detached. Changes made to entities that
* have not been flushed to the database will not be
* persisted.
*/
public void clear();
entityManager.detach(entity);
Supprimer l'entité donnée du contexte de persistance
détacher
/**
* Remove the given entity from the persistence context, causing
* a managed entity to become detached. Unflushed changes made
* to the entity if any (including removal of the entity),
* will not be synchronized to the database. Entities which
* previously referenced the detached entity will continue to
* reference it.
* @param entity entity instance
* @throws IllegalArgumentException if the instance is not an
* entity
* @since Java Persistence 2.0
*/
public void detach(Object entity);