2

我得到了著名的 LazyInitializationException。

我有一个对象 User 存储在会话中。该对象包含另一个延迟初始化的对象 Market。当我在会话中加载用户时,我不加载 Market,因为它太重了,我不需要每次都需要它。

当我想加载市场时,我处于不同的事务中,我不想从数据库中重新加载用户。如何检索 Market 对象?知道 User.market 包含 Hibernate 代理和市场的 id,并且我不想使用反射来破解 Hibernate。

如果我可以加载市场而不将其加载到用户中,那就更好了。由于用户在会话中,我不想在会话中放很多东西。

JPA 兼容的解决方案会更好。

干杯

4

5 回答 5

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 解决方案,只是一种解决方法。

于 2013-02-06T10:43:21.123 回答
1

您需要做的是注释访问器而不是字段。这将允许您在最初加载用户时避免加载市场对象,但您可以从 Hibernate 代理对象访问市场的 id,而不会触发延迟加载或获得 LazyInitializationException。然后稍后当您想要加载市场本身时,您会根据其 id 进行正常的实体检索。您可以在此处阅读有关其工作原理的详细说明。

于 2013-02-07T05:48:48.900 回答
1

为什么明显的解决方案不好?就像建议的一个ring0一样,或者如果您已经在对象中拥有 id,则只需使用findByIdor方法。findUser

//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),您可能与每个新事务都有一个新会话。如果是这种情况,您无需担心在其中放太多东西。您可以在此处找到有关上下文会话的更多信息。

于 2013-02-06T10:57:34.137 回答
1

如果关系是双向的,那么您可以使用带有子句的查询独立加载市场where market.user.id = ?

于 2013-02-06T10:36:08.220 回答
0

既然您提到了新事务,那么您可能会使用属于线程的新休眠会话,

在与休眠会话直接交互的情况下使用此

   obj = session.merge(obj);

如果您使用 JPA2 Api

   obj=   entityManager.merge(obj);

如果有帮助,请评价答案。干杯

于 2013-02-06T10:46:31.747 回答