Hibernate / Spring:在@Transactional中加载延迟集合时出错

时间:2010-09-15 09:40:57

标签: java hibernate spring lazy-loading

我虽然理解懒惰/急切的加载,但显然我没有:

我有一个标记为@Transactional的服务,但当我尝试操作列表时(访问其对象),我得到“org.hibernate.LazyInitializationException:无法懒惰地初始化角色集合:tld.myproduct .data.entities.CategoryType.translatableText,没有会话或会话被关闭“。为什么我无法访问我的底层对象的任何建议?

更新:异常发生在“type.getTranslatableText()。size()”行

干杯

的Nik

// The service
@Service("categoryTypeService")
@Transactional("transactionManager")
public class CategoryTypeServiceImpl extends AbstractCRUDServiceImpl<CategoryType, Integer> implements CategoryTypeService {

    @SuppressWarnings("unchecked")
    @Override
    public List<CategoryType> getAll() {
        List<CategoryType> list = DAO.getSession().createCriteria(CategoryType.class).list();

        for(CategoryType type : list)   
            type.getTranslatableText().size();  // Access TranslatableText to demonstrate problem

        return list;
    }

}


// The entity
@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@Configurable(preConstruction=true)
public class CategoryType {

    @Id
    @Column(nullable = false)
    private Integer id;

    @Column(length = 50, nullable = true)
    private String description;

    @Column(name = "TranslatableDescriptionId", nullable = false)
    private Integer TranslatableDescriptionId;

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumn(name = "Id", referencedColumnName="TranslatableDescriptionId", insertable=false, updatable=false)
    private Set<TranslatableText> translatableText;

    /** getters and setters **/
}

1 个答案:

答案 0 :(得分:2)

以下是Open Session in View问题的一般性讨论。我建议你阅读这篇文章。

简单来说,您有3种可能的解决方案:

1)不要对集合进行延迟加载(当然,如果它不重要,应该以某种方式测试性能):

@OneToMany(fetch=FetchType.EAGER)   //   <-- it's not lazy any more
@JoinColumn(name = "Id", referencedColumnName="TranslatableDescriptionId", insertable=false, updatable=false)
private Set<TranslatableText> translatableText;

2)您可以在View Filter(或OpenEntityManagerInViewFilter)中使用Open Session,但这将使您的会话保持打开状态,直到页面加载完成(可能是几秒钟)。

它可能会导致性能问题,更有可能的是,当一个用户正在更改对象而另一个用户具有打开的休眠会话时,您将获得这种情况。我不知道到底发生了什么,但如果你想确保你的应用程序是健壮的,你应该找到它。

3)当你需要从数据库加载一些集合时,只需执行JPA查询并使用特殊的DAO方法获取所有必需的数据(这意味着字段translatableText将从CategoryType类中消失) 。最强大的解决方案,但你需要做一些额外的工作来实现它,它比以前的两个选项更难。