Spring Boot Data JPA - Aktualisierungsabfrage ändern - Persistenzkontext aktualisieren
Ich arbeite mit Spring Boot 1.3.0.M4 und einer MySQL-Datenbank.
Ich habe ein Problem beim Ändern von Abfragen. Der EntityManager enthält veraltete Entitäten, nachdem die Abfrage ausgeführt wurde.
Original JPA Repository:public interface EmailRepository extends JpaRepository<Email, Long> {
@Transactional
@Modifying
@Query("update Email e set e.active = false where e.active = true and e.expire <= NOW()")
Integer deactivateByExpired();
}
ngenommen, wir habenEmail [id = 1, a, ctive = true, expire = 2015/01/01] in DB.
Nach der Ausführung:
emailRepository.save(email);
emailRepository.deactivateByExpired();
System.out.println(emailRepository.findOne(1L).isActive()); // prints true!! it should print false
Erster Lösungsansatz: @ hinzufügclearAutomatically = truepublic interface EmailRepository extends JpaRepository<Email, Long> {
@Transactional
@Modifying(clearAutomatically = true)
@Query("update Email e set e.active = false where e.active = true and e.expire <= NOW()")
Integer deactivateByExpired();
}
Dieser Ansatz löscht den Persistenzkontext, um keine veralteten Werte zu haben, löscht jedoch alle nicht gelöschten Änderungen, die im EntityManager noch ausstehen. Da ich nur @ benutsave()
Methoden und nichtsaveAndFlush()
Einige Änderungen gehen für andere Entitäten verloren:
public interface EmailRepository extends JpaRepository<Email, Long>, EmailRepositoryCustom {
}
public interface EmailRepositoryCustom {
Integer deactivateByExpired();
}
public class EmailRepositoryImpl implements EmailRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
@Transactional
@Override
public Integer deactivateByExpired() {
String hsql = "update Email e set e.active = false where e.active = true and e.expire <= NOW()";
Query query = entityManager.createQuery(hsql);
entityManager.flush();
Integer result = query.executeUpdate();
entityManager.clear();
return result;
}
}
Dieser Ansatz funktioniert ähnlich wie@Modifying(clearAutomatically = true)
erzwingt jedoch zuerst, dass der EntityManager alle Änderungen in die Datenbank schreibt, bevor das Update ausgeführt wird, und löscht dann den Persistenzkontext. Auf diese Weise gibt es keine veralteten Entitäten und alle Änderungen werden in der Datenbank gespeichert.
Ich würde gerne wissen, ob es eine bessere Möglichkeit gibt, Update-Anweisungen in JPA auszuführen, ohne dass das Problem der veralteten Entitäten auftritt und ohne dass das manuelle Flush in die Datenbank erfolgt. Deaktivieren Sie möglicherweise den Cache der zweiten Ebene? Wie kann ich das im Spring Boot machen?
Update 2018
Spring Data JPA hat meine PR genehmigt, es gibt einflushAutomatically
Option in@Modifying()
jetzt
@Modifying(flushAutomatically = true, clearAutomatically = true)