1

我有休眠 pojo 类 A { B b ; 其他一些属性},对于 B 类,lazy=true。当我得到对象 A 时,B 没有被加载并且休眠返回它的代理。当我将此对象传递给另一个模块时,该模块遍历 A 中的每个对象,当它遇到 B.getXXX 时,它会抛出 LazyInitialization 异常。在这种特殊情况下,我不想加载 B 类,因为它不是必需的。当我在 B 上调用方法时,有什么方法可以返回 null 或将 B 的代理转换为真实对象 B,这样模块就不会引发 LazyInitialization 错误。我无法将 B 类 getter、setter 更改为普通类并被许多其他类使用。

4

4 回答 4

1

如果我理解您的问题,您正在检索与 B 具有惰性关联的对象 A。但是,此关联未初始化,并且您发现其他模块正在抛出异常,因为 B 实际使用。所以它在某种程度上是必需的。

你想要么

  • null从调用返回B(据我所知,这是不可能的,除非这些模块上有一些特定于应用程序的行为,只有你才能知道)或

  • B发生此类调用时进行初始化。我会尽力帮助你实现这个。

你得到的原因LazyInitializationExceptions是获取(并且没有初始化它)的会话B已经关闭,所以在这一点上,实例B根本没有用。您可以在此处应用的一种解决方法是使用OSIV 模式,以便在所有请求范围内打开相同的 Hibernate 会话。这是将A使用惰性获取B在需要时进行初始化B的会话。

您可以应用的另一个选项是B在另一个会话中初始化(仅当这些异常发生在另一个事务的上下文中时才有效,也就是说,另一个 Hibernate 会话打开,与 fetched 的会话不同A)。例如:

session.update(a.getB());

当然,您总是可以强制初始化BwithfetchMode.EAGERHibernate.initialize(a.getB())。但这将无条件地加载实例,即使它根本不会被使用。

此外,您可能会发现这个问题的答案可能很有用:hibernate: LazyInitializationException: could not initialize proxy

于 2011-09-27T11:54:53.090 回答
0

实际上,您有几个选择。

1) 建立 A->B 关系 EAGER。

2)LazyInitializationExceptions当您在休眠会话已经关闭时尝试启动代理时,您会得到。所以他可能的解决方案是保持会话打开,直到你所有的 A、B、C ......等对象操作都没有完成。

3)如果你对WEB环境有所了解,可以看到一种叫做Open Session的模式。它使您的 Hibernate 会话保持打开状态,直到您的 HTTP 请求处于活动状态。

I you can read more about it here. I think it will be useful for you to read it.

于 2011-09-27T12:14:54.403 回答
0

Don't send the entities to other modules when the session is closed.

If these other module is executed in the same Application Domain as the session, keep the session open when calling the module and close it when it returns.

If these module is not in the same AppDomain, if you need some kind of serialization to send the objects or if it is called asynchronously, I would use a DTO. Exposing the entities outside of the server (I don't know if this is the case here) is a bad practice for several reasons. Ayende Rahien calls it the Stripper Pattern.

于 2011-09-27T12:40:35.650 回答
0

Thanks for all your suggestion. My application have layered architecture. Service->Manager->Dao. Hibernate session closes after manager. Other module interacts only through Service. Opening hibernate session till request complete is not an option for me. I also do not want to hit database as it is not necessary that properties of B are populated. I just want to replace hibernate proxy with real object so that anyone who is using service do not face any problem. I found a utility at http://svn.rhq-project.org/repos/rhq/branches/HEIKO-EXP/modules/enterprise/server/safe-invoker/src/main/java/org/rhq/enterprise/server/util/HibernateDetachUtility.java which exactly does what i want. It inspect object and replace hibernate proxy with real object. I need to customize following things in above utility 1. Change instances of classname from org.rhq to my package structure. 2. They expect name of identity field in pojo is "id". I change it to use those property which has annotation of javax.persistence.Id.

Basic testing with above changes is done and it is working fine. I just need to test whole application with various scenario so that it is working in all scenario.

于 2011-09-28T08:35:59.417 回答