我得到了着名的LazyInitializationException。
我有一个存储在会话中的对象User。该对象包含一个其他对象Market,它是惰性初始化的。 当我在会话中加载用户时,我不会加载Market因为它太重而且我不是每次都需要它。
当我想加载市场时,我处于不同的交易中,我不想从数据库重新加载用户。如何检索Market对象?知道User.market包含Hibernate代理,因此市场的ID和我不想用反射来破解Hibernate。
如果我可以加载市场而不将其加载到用户中,那将会更好。由于用户在会话中,我不想在会话中放入大量内容。
JPA兼容的解决方案会更好。
干杯
答案 0 :(得分:2)
如果热门模式提取不可接受,并且如果交易无法维持到市场检索,则可以实施特定的dao方法以从用户专门检索市场
public List<Market> retrieveMarketFromUser (final User user) {
Query query = session.createQuery("SELECT m FROM User AS u INNER JOIN u.market as m WHERE u.userid = :uid");
query.setParameter("uid", user.getId());
List<Market> list = query.list();
return list;
}
或简短版
Query query = session.createQuery("SELECT u.market FROM User AS u WHERE u.userid = :uid");
这可能不是您期望的JPA解决方案,只是一种解决方法。
答案 1 :(得分:1)
如果关系是双向的,那么您可以使用where market.user.id = ?
之类的子句独立加载市场。
答案 2 :(得分:1)
为什么明显的解决方案不好?与建议的ring0一样,或者如果您已在findById
对象中拥有ID,则只需使用find
或User
方法。
//if using a session factory
session.findById(Market.class, marketId);
//if using the EntityManager
em.find(Market.class, marketId);
根据current_session_context_class
配置的方式(我在hibernate.cfg.xml
中拥有它),您可能会在每个新事务中都有一个新会话。如果是这种情况,你不必担心在那里放太多东西。您可以在上下文会话中找到更多信息here。
答案 3 :(得分:1)
您需要做的是注释访问者而不是字段。这将允许您在最初加载用户时避免加载市场对象,但您可以从Hibernate代理对象访问市场ID,而不会触发延迟加载或获取LazyInitializationException。然后,当您想要加载市场本身时,您可以根据其ID进行正常的实体检索。您可以阅读有关其工作原理的详细说明here。
答案 4 :(得分:-1)
既然你已经提到了新的事务,那么你可能会使用属于线程的新的hibernate会话,
使用这种与hibernate会话的直接交互
obj = session.merge(obj);
如果您使用JPA2 Api
obj= entityManager.merge(obj);
如果有帮助,请评价答案。 干杯