Spring和Hibernate:DAO模式。如何解决LazyInitializationException

时间:2012-10-08 11:02:00

标签: spring hibernate dao lazy-initialization

我想知道:使用DAO模式的一对(多对多)FetchType.LAZY有什么意义? 它基本没用?一旦你在你的DAO之外(例如,实际工作已经完成),你就不能获取相关数据,因为你不再在休眠会话中了。

让我们举个例子:

StudentClass。一个学生上了很多课。他现在登录系统,并从系统中检索他的Student实体对象。

application layer -> Service Layer -> DAO

现在学生想要看看他参加了哪些课程,并且因为我们在DAO之外而发生了LazyInitializationException

有什么方法可以防止这种情况发生?我喜欢googled hours并没有找到解决方案,除了在离开DAO之前实际取出所有东西,这首先打败了懒惰的目的。 (已阅读OpenSessionViewFilter,但这应该独立于应用程序层工作)

你如何以一种好的方式解决这个问题?什么是不受此影响的替代模式?

编辑:

我没有LazyInitializationException以下设置:

@OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.compound", 
        cascade = CascadeType.ALL, orphanRemoval = true)
@Fetch(FetchMode.JOIN)

有趣的是它一定是这样的。

删除@Fetch - > LazyInitializationException

更奇怪的是,如果我删除orphanRemoval = true,那么即使LazyInitializationException也会出现@Fetch。所以这两个都是必需的。

也许有人可以告诉我为什么会这样。目前我倾向于完全抛弃休眠,就像纯JDBC一样,我会在几个小时前达到预期的行为......

2 个答案:

答案 0 :(得分:1)

您可以随时获取外键关系数据而无需相同的激情。由于您的会话不存在于应用程序层之外,因此您只需在检索数据并进行设置的方法中手动获取它。

应用层:

public List<SchoolClass> getSchoolClassesByStudent(Serializable identifier)
{
    List<SchoolClasses> schoolClasses = // get classes by student using criteria or hql
    return schoolClasses;
}

客户层:

public void loadSchoolClassesByStudent(Student student)
{
    student.setSchoolClasses(application.getSchoolClassesByStudent(student.getId()));
}

我自己选择不支持我的休眠实体中的任何集合 我使用非常通用的方法获取所有子关系,我的服务器提供给我的客户端类似于此。

编辑:或者创建一些逻辑(拦截器?),如果数据在访问之前未经初始化并且使用通用方法初始化,则可以在DAO外部进行检查。 这也假设Hibernate jar是在客户端级别,这取决于这是一个好主意(如果未初始化的数据未设置为null,则相同)。

答案 1 :(得分:0)

解决问题的一种方法是使用OpenSessionInViewFilter过滤器。

<filter>
    <filter-name>hibernateSessionFilter</filter-name>
    <filter-class>
        org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    </filter-class>
</filter>