使用JPA2/Hibernate,我创建了一个实体A,该实体具有到实体X的单向映射(请参见下文)。在A内,我还尝试使用@PostLoad方法计算 transient 成员“t”。计算需要访问关联的X:

@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)在初始化“listOfX”成员之前,调用我的@PostLoad方法
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()访问器中,并添加一个同步块(synchronized block)。但是,我想避免这种情况。

那么,有没有一种方法可以在调用@PostLoad之前执行渴望的获取?我不知道JPA可以做到这一点,所以我希望有一些我不知道的东西。

另外,也许Hibernate的专有API可以控制这种行为吗?

最佳答案

这可能为时已晚,但是休眠似乎不支持默认的jpa fetchtype选项。

@OneToMany(orphanRemoval = false, fetch = FetchType.EAGER)

您必须使用特定的休眠模式:
@LazyCollection(LazyCollectionOption.FALSE)

关于jpa-2.0 - 急于执行@PostLoad _after_吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4498262/

10-10 04:20