java - query - spring data repository



Pourquoi les modifications ne sont-elles pas générées par une requête de mise à jour avec Spring Data JPA? (1)

La raison pour laquelle vous voyez cela fonctionner comme il fonctionne est assez simple: JPA est défini pour fonctionner de cette façon.

Je suppose que vous déclenchez une requête de mise à jour pour updateCamelName(…) . La spécification JPA indique ce qui suit pour les opérations de mise à jour et de suppression:

Le contexte de persistance n'est pas synchronisé avec le résultat de la mise à jour en masse ou de la suppression.

Des précautions doivent être prises lors de l'exécution d'opérations de mise à jour ou de suppression groupées car elles peuvent entraîner des incohérences entre la base de données et les entités du contexte de persistance actif. En général, les opérations de mise à jour et de suppression en masse ne doivent être effectuées que dans une transaction dans un nouveau contexte de persistance ou avant d'aller chercher ou d'accéder à des entités dont l'état pourrait être affecté par de telles opérations.

Cela signifie que si vous avez besoin de voir les changements d'une telle opération, vous devez faire les choses suivantes:

  1. Effacez EntityManager après cette opération. Spring Data L'annotation @Modifying de JPA a un indicateur clearAutomatically défaut à false . Si ce paramètre est défini sur true, l'invocation de la méthode de requête EntityManager automatiquement (comme son nom l'indique.) Utilisez cette option avec précaution car elle supprimera toutes les modifications en attente qui n'ont pas encore été vidées dans la base de données!
  2. Re-obtenir une nouvelle instance de l'entité à partir de l' EntityManager . Appeler findOne(…) sur le dépôt semble être un moyen raisonnable de le faire car cela se traduit grossièrement en EntityManager.find(…) . Sachez que cela peut toujours atteindre les caches de second niveau configurés sur le fournisseur de persistance.

Le moyen le plus sûr de contourner ce problème est - comme le suggère la spécification - d'utiliser les requêtes de mise à jour uniquement pour les opérations en bloc et de revenir par défaut à l'approche «load entity, alter, merge».

J'ai le service suivant:

@Service
public class CamelService {

    @Transactional
    public aCamelThing() {

          Camel camel = this.camelRepository.findOne(1);

          System.out.println(camel.getCamelName());  // prints "normalCamel"

          // simple hql set field 'camelName'
          int res = this.camelRepository.updateCamelName(1,"superCamel!");

          Camel camelWithNewName = this.camelRepository.findOne(1);

          System.out.println(camelWithNewName .getCamelName());  // prints "normalCamel" ?!?!?

    } 
}

Toute idée comment puis-je atteindre l'objectif que la deuxième impression imprimera: "superCamel!" ? (séparer le second appel d'une nouvelle transaction n'est pas idéal).





spring-data