在DAO方法中访问延迟加载的集合时出现NullPointerException

Roc*_*ein 8 java spring multithreading hibernate lazy-loading

在应用程序中运行多个线程时,我遇到了Spring和Hibernate的奇怪问题.我正在使用spring 3.2.0.RELEASE和hibernate 4.1.12.Final.问题是,对于某些对象,当从db检索它们时,检索成功,但未设置所有映射的集合.这是我的回购的一个例子:

@Repository("fooRepository")
public class FooRepository {

    private static final Logger log = Logger.getLogger(FooRepository.class);

    @Autowired
    private SessionFactory sessionFactory;

    @Override
    @Transactional
    public Foo retrieve(final Long id) {
        Foo instance = (Foo) sessionFactory.getCurrentSession().get(Foo.class, id);
        for (CollectionMember member : instance.getCollectionMembers()) {
            log.debug(member.getId());      
        }
        return instance;
    }
Run Code Online (Sandbox Code Playgroud)

对于某些对象,此方法在尝试访问CollectionMember列表时始终抛出以下错误:

Caused by: java.lang.NullPointerException
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:501)
Run Code Online (Sandbox Code Playgroud)

问题是session.get()调用为所有延迟加载的集合创建PersistentBag对象,但从不设置内容.仅在启用多线程时才会发生这种情况.任何人都可以解释为什么会这样吗?

编辑:这是foo类的相关位:

@Entity
@Table(name = "FOO")
@XmlRootElement(name = "foo")
public class Foo {

    @EmbeddedId
    private FooPK id;

    @OneToMany
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumns({
            @JoinColumn(name = "COLLECTION_ID", referencedColumnName = "COLLECTION_ID"),
            @JoinColumn(name = "FOO_ID", referencedColumnName = "FOO_ID")})
    private List<CollectionMember> collectionMembers = new ArrayList<CollectionMember>();
Run Code Online (Sandbox Code Playgroud)

而CollectionMember类:

@Entity
@Table(name = "COLLECTION_MEMBER")
@XmlRootElement(name = "collectionMember")
public class CollectionMember {

    @EmbeddedId
    private CollectionMemberPK primaryKey;

    @ManyToOne
    @JoinColumn(name = "COLL_CODE")
    private CollectionCode collectionCode;
Run Code Online (Sandbox Code Playgroud)

Aar*_*ron 0

多线程在哪里发挥作用?如何确保单个线程始终使用相同的休眠会话?

我理解hibernate和延迟加载的方式是,当你遍历集合时,Hibernate将在CurrentSession中查找。在多线程环境中,该会话可能已被另一个线程使用。我不确定 @Transactional 是否足以保留相同的 Hibernate 会话。

可能有一个 Hibernate 配置用于此目的。