急切地执行@PostLoad _after_?

问题描述 投票:11回答:3

使用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)

在调试时查看hibernate的代码(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块。但是,我想避免这种情况。

那么,有没有办法在调用@PostLoad之前执行急切的提取?我不知道有这样做的JPA设施,所以我希望有一些我不知道的事情。

另外,也许Hibernate的专有API有控制这种行为的东西?

jpa-2.0 hibernate3
3个回答
2
投票

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

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

你必须使用特定于hibernate的一个:

@LazyCollection(LazyCollectionOption.FALSE)

0
投票

我不知道如何解决这个问题,但我认为一点点重构可能有所帮助,我的想法是将代码移到@PostConstruct

所以例如你的班级将是:

@Entity  
public class A {  
    // ...
    @Transient
    int t;

@OneToMany(orphanRemoval = false, fetch = FetchType.EAGER)  
private List listOfX;  

@PostConstruct
public void calculateT() {
    t = 0;
    for (X x : listOfX)
        t = t + x.someMethod();
}

}

一旦完成初始化bean的所有容器服务,服务器将立即调用PostConstruct。


0
投票

更新了错误报告的链接:

https://hibernate.atlassian.net/browse/HHH-6043

这在4.1.8和4.3.0或更高版本中得到修复

© www.soinside.com 2019 - 2024. All rights reserved.