Используя JPA2/Hibernate, я создал объект A, который имеет однонаправленное сопоставление объекту X (см. ниже). Внутри A у меня также есть временный член "t", который я пытаюсь вычислить с помощью метода @PostLoad. Для вычисления требуется доступ к ассоциированной Xs:
@Entity
public class A {
// ...
@Transient
int t;
@OneToMany(orphanRemoval = false, fetch = FetchType.EAGER)
private List listOfX;
@PostLoad
public void calculateT() {
t = 0;
for (X x : listOfX)
t = t + x.someMethod();
}
}
Однако, когда я пытаюсь загрузить этот объект, я получаю ошибку "org.hibernate.LazyInitializationException: незаконный доступ к загрузке коллекции".
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:363)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.get(PersistentBag.java:445)
at java.util.Collections$UnmodifiableList.get(Collections.java:1154)
at mypackage.A.calculateT(A.java:32)
Глядя на спящий код (AbstractPersistentCollection.java) во время отладки, я обнаружил, что:
1) Мой метод @PostLoad вызывается до того, как элемент "listOfX" инициализирован
2) Код Hibernate имеет явную проверку, чтобы предотвратить инициализацию коллекции с нетерпением из-за @PostLoad:
protected final void initialize(boolean writing) {
if (!initialized) {
if (initializing) {
throw new LazyInitializationException("illegal access to loading collection");
}
throwLazyInitializationExceptionIfNotConnected();
session.initializeCollection(this, writing);
}
}
Единственный способ, которым я решил исправить это, - это прекратить использование @PostLoad и переместить код инициализации в getT() accessor, добавив синхронизированный блок. Тем не менее, я хочу этого избежать.
Итак, есть ли способ, с помощью которого можно было бы получать желаемые результаты перед вызовом @PostLoad? Я не знаю возможности JPA для этого, поэтому я надеюсь, что там что-то не знаю.
Кроме того, возможно, что у Hibernate API есть что-то, чтобы контролировать это поведение?