Java Hibernate,无法初始化延迟加载但想忽略这些字段

时间:2017-03-06 19:42:32

标签: java hibernate

我有以下实体(连接到db):

@Entity
public class Campaign {
  // ...
  @OneToMany(fetch = FetchType.LAZY)
  private List<Subscriber> subscribers;
}

@Entity
public class Subscriber {
  // ...
}

我想获取广告系列但忽略订阅者。在我的控制器中,我jsonify广告系列,但会触发错误,因为它会尝试延迟加载订阅者。在这种情况下,我不希望它延迟加载订阅者,只打印出广告系列(在其他情况下我想要打印出来)。

我尝试在hql查询中选择特定字段,但返回的数组不是对象。

3 个答案:

答案 0 :(得分:2)

正如@Gimbly所说,我正在错误地查看问题,需要查看序列化对象的内容。我从以下帖子得到了答案:

Avoid Jackson serialization on non fetched lazy objects

答案 1 :(得分:1)

只有当某人执行方法getSubscribers()(实际上是代理列表)时,才会触发订阅者数据库查询。

因此,如果subscribers字段为空,则永远不会触发查询。

也就是说,快速(但不是那么干净)的解决方案是创建一个方法,将null设置为此字段,但不改变数据库,如下所示:

@PersistentContext
private EntityManager em;

/* ... */

private void detachCampaigns(List<Campaign> campaigns){
    for(Campaign c: campaigns){
        em.detach(c);           // Exclude from JPA context
        c.setSubscribers(null); // inhibits lazy proxy list
    }
}

方法detachCampaigns()将:

  • 从JPA上下文(内存)中分离每个广告系列对象。从现在开始,对它们的任何修改都不会应用于数据库。
  • 将订阅者列表设置为null覆盖代理对象,因此如果您的代码尝试调用getSubscriers(),则无法访问数据库以避免出现问题。

在此之后,您只需在json化广告系列之前调用此方法。

答案 2 :(得分:0)

主要问题是您要序列化实体而不是只读投影。

在后一种情况下,您可以轻松定义结果中要包含的字段,而不必处理任何延迟加载问题。

仅在需要更改状态时才使用实体。

对于创建投影,您可以使用基本定义界面的Spring Data JPA way,框架将处理其他界面。

如果您无法使用Spring Data JPA,那么您可以将投影定义为类,并通过JPQL / HQL / Criteria API甚至本机查询获取必要的属性。