我有休眠pojo class A {B b;一些其他的适当性}对于B类,lazy = true。 当我得到对象A时,B没有被加载,并且hibernate返回它的代理。当我将这个对象传递给另一个模块时,该模块遍历A中的每个对象,当它遇到B.getXXX时,它会抛出LazyInitialization异常。在这种特殊情况下,我不想加载B类,因为它不是必需的。有没有什么办法,当我调用B方法时,它会返回null或将B的代理转换为实际对象B,以便模块不会引发LazyInitialization错误。我不能改变B类的getter,setter作为普通的类并且被其他类使用。从休眠会话中删除对象
回答
感谢您的所有建议。 我的应用程序有分层架构。服务 - >管理器 - >道。经理之后Hibernate会话关闭。其他模块只能通过服务进行交互。打开休眠会话,直到请求完成不是我的选择。我也不想打数据库,因为B的属性没有必要填充。我只想用真实对象替换Hibernate代理,以便任何使用服务的人都不会遇到任何问题。我在 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 找到一个实用程序,它正是我想要的。它检查对象并用真实对象替换Hibernate代理。我需要在上述实用程序中自定义以下内容 1.将org.rhq中的classname实例更改为我的包结构。 2.他们期望pojo身份字段的名称是“id”。我将其更改为使用具有javax.persistence.Id注释的那些属性。
基本测试与上述更改已完成,它工作正常。我只需要在各种情况下测试整个应用程序,以便它可以在所有情况下工作。
如果我理解你的问题,你正在检索一个对象A与B有懒关联。但是,这个关联没有被初始化,并且你发现其他模块抛出了异常,因为实际上使用了B。所以它在某种程度上需要是。
你想要么
返回
null
从到B
电话(不可能的,因为据我所知,除非有这些模块的一些应用程序特定的行为,只有你可以知道)或当这样的呼叫发生时初始化
B
。我会尽力帮助你实现这一个。
为什么你得到LazyInitializationExceptions
的原因是,该获取B
(并没有初始化)会议已经关闭,所以在这一点上,B
实例是没有用的,在所有。您可以在此应用的一种解决方法是使用OSIV pattern,以便在所有请求范围中打开相同的Hibernate会话。这是将会获取A
与懒惰B
和将会初始化B
当需要会话。 (如果这些异常都在另一个事务的情况下发生的唯一有效的,那就是,与另一个Hibernate会话,从获取A
的一个不同)
你可以申请另一种选择是在另一个会话初始化B
。例如:
session.update(a.getB());
当然,你总是可以强制B
初始化与fetchMode.EAGER
或Hibernate.initialize(a.getB())
。但是,无条件地加载实例,即使它根本不会被使用。
此外,你可以找到这个问题的答案可能是有用的:hibernate: LazyInitializationException: could not initialize proxy
其实,你有几个选项。
1)使A-> B关系EAGER。
2)当您尝试在休眠会话已关闭时尝试启动代理时,您会收到LazyInitializationExceptions
。所以他可能的解决方案是保持Session打开,直到所有的A,B,C ...等对象操作都没有完成。
3)如果您对WEB环境感兴趣,有一种称为Open Session的模式。这会使您的Hibernate会话保持打开状态,直到HTTP请求处于活动状态。你可以阅读更多关于here。我认为这对您阅读会很有帮助。
当会话关闭时,不要将实体发送到其他模块。
如果这些其他模块在与会话相同的应用程序域中执行,请在调用模块时保持会话打开,并在返回时关闭它。
如果这些模块不在同一个AppDomain中,如果您需要某种序列化来发送对象,或者如果它是异步调用的,我会使用DTO。暴露服务器之外的实体(我不知道这是否是这种情况)是一个不好的做法,原因有几个。 Ayende Rahien称之为Stripper Pattern。
- 1. 从休眠中的会话中删除对象?
- 2. 休眠:删除子对象
- 3. 休眠 - 删除对象引用而不删除对象
- 4. 删除休眠相关对象和Spring
- 5. 删除休眠相关对象
- 6. 休眠:从合并会话
- 7. 从具有休眠ManyToMany关系的集合中删除对象
- 8. 休眠不会删除我的对象。为什么?
- 9. [N]休眠会话
- 10. 休眠 - 无法删除父对象的子对象
- 11. 休眠ManyToMany删除
- 12. 休眠和从列表中删除
- 13. 休眠 - 从集合中删除项目
- 14. 休眠saveOrUpdate与会话中的另一个对象
- 15. 休眠的EntityManager:如何删除协会
- 16. 一键删除与onetomany协会休眠
- 17. 休眠:从列表中删除项目不会持续
- 18. 休眠会话错误
- 19. SEAM /休眠:一个会话
- 20. 休眠会话关闭
- 21. 休眠会话处理
- 22. EntityManager和休眠会话
- 23. 休眠会话线程
- 24. Vaadin休眠会话错误
- 25. JMS与休眠会话
- 26. 管理休眠会话
- 27. 休眠会话范围
- 28. 休眠一对多集合删除
- 29. 休眠多对一级联删除
- 30. 在休眠状态下从会话对象中识别特定的CRUD操作
我同意将域名暴露给外界不是很好的做法。不幸的是,它是旧代码,我不能更改方法签名来使用DTO而不是域。在我的应用程序中,约有98%使用DTO,但导致问题的地方很少。 – dmay