Spring Boot Data JPA - Изменение запроса на обновление - Обновить контекст постоянства
Я работаю с Spring Boot 1.3.0.M4 и базой данных MySQL.
У меня проблема при использовании модифицирующих запросов, EntityManager содержит устаревшие сущности после выполнения запроса.
Оригинальный репозиторий JPA: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();
}
Предположим, у нас естьEmail [id = 1, a, ctive = true, expire = 2015/01/01] в БД.
После выполнения:
emailRepository.save(email);
emailRepository.deactivateByExpired();
System.out.println(emailRepository.findOne(1L).isActive()); // prints true!! it should print false
Первый подход к решению проблемы: добавитьclearAutomatics = 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();
}
Этот подход очищает контекст постоянства, чтобы не иметь устаревших значений, но он удаляет все невыгруженные изменения, все еще ожидающие в EntityManager. Как я использую толькоsave()
методы и неsaveAndFlush()
некоторые изменения потеряны для других объектов :(
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;
}
}
Этот подход работает аналогично@Modifying(clearAutomatically = true)
но сначала он заставляет EntityManager сбросить все изменения в БД перед выполнением обновления, а затем очищает контекст постоянства. Таким образом, не будет устаревших объектов, и все изменения будут сохранены в БД.
Я хотел бы знать, есть ли лучший способ выполнить операторы обновления в JPA, не имея проблемы устаревших сущностей и без ручного сброса в БД. Возможно, отключение кэша 2-го уровня? Как я могу сделать это в Spring Boot?
Обновление 2018
Spring Data JPA одобрила мой пиар, естьflushAutomatically
вариант в@Modifying()
сейчас.
@Modifying(flushAutomatically = true, clearAutomatically = true)