Так что вот немного контекста, у меня возникла ситуация, когда hibernate или spring-data игнорируют предложение where и возвращают кешированный объект, и я не могу найти почему.
Пример кода :
//The entities are mapped properly with standard getters, setters, equals and hashCodes.
public class Foo {
private Long id;
private Set<Bar> bars;
}
public class Bar {
private Long id;
private String name;
private Boolean active;
}
public class FooRepository extends ... {
@Query("FROM Foo f LEFT JOIN FETCH f.bars b WHERE f.id = :id AND b.active = true")
Optional<Foo> findByIdWithActiveBars(Long id);
}
// problematic method
public Foo remove(Long id, names) {
methodA(id, names);
return fooRepository.findByIdWithActiveBars(id);
}
@Transactional(propagation= Propagation.SUPPORTS)
public void methodA(long id, Set<String> names) {
final Optional<Foo> foo = fooRepository.findById(id);
invalidateBars(foo, names);
}
private void invalidateBars(Foo foo, Set<String> names) {
final Set<Bar> barsToUpdate = new HashSet<>();
foo.getBars().stream()
.filter(names.contains(bar.getName())
.forEach(bar -> {
bar.setActive(false)
barsToUpdate.add(bar);
);
barRepository.saveAll(barsToUpdate);
}
Проблема с приведенным выше кодом заключается в том, что метод remove всегда возвращает объект foo со всеми барами it (включая те, которые имеют активное значение false), но если я прокомментирую вызов methodA, тогда результат fooRepository.findByIdWithActiveBars (id) будет таким, как и ожидалось (к объекту foo прикреплены только активные столбцы).
Сначала я подумал, что использование barRepository "разрушает" кэш из-за родительского объекта не обновлялся (даже несмотря на то, что коллекция bar находится в hashCode foo и равна, поэтому он должен отличаться), и объект, кэшированный первым findById, выполненным в методе methodA, был возвращен результат (все же это игнорировало бы предложение where) поэтому после небольшого копания на net я нашел исправление: добавьте
entityManager.clear();
в конце Methoda. Но я не удовлетворен, так как хочу знать причину этой проблемы. Я почти уверен, что это связано с кэшем первого уровня в Hibernate, но я не могу понять, почему.
Я был бы очень рад, если бы кто-то мог пролить мне свет на эту проблему.