OneToMany关系不起作用

Ema*_*uel 21 java entity jpa one-to-many

我的表:

产品:id,名称

优惠:id,value,product_id

实体:

@Entity
@Table(name="product")
public class Product implements Serializable {
    @OneToMany(mappedBy="product")
    private Set<Offer> offers;
    ...
}

@Entity
@Table(name="offer")
public class Offer implements Serializable {
    @ManyToOne
    @JoinColumn(name="PRODUCT_ID")
    private Product product;
    ...
}
Run Code Online (Sandbox Code Playgroud)

当我尝试从表中获取一些数据时Product,我得到一个java.lang.NullPointerException,并且这段代码:product.getOffers()返回:

{IndirectSet:未实例化}

如何解决这个问题?

Tom*_*asz 26

不是错误消息.print指令导致在底层IndirectSet上调用toString().

当从数据库中读取包含域对象时,TopLink将在实例变量中放置IndirectSet.将第一条消息发送到IndirectSet后,将从数据库中提取内容并恢复正常的Set行为.

IndirectCollection类型是专门实现的,不在toString()上实例化:

出于调试目的,#toString()不会触发数据库读取.

但是,对间接集合的任何其他调用(例如size()或isEmpty())都将实例化该对象.

当一个"委托"方法首次调用getDelegate()时,最终会触发数据库读取,而getDelegate()又调用buildDelegate(),它将消息getValue()发送给值持有者.值持有者执行数据库读取.将第一条消息发送到IndirectSet后,将从数据库中提取内容并恢复正常的Set行为.

另请参见IndirectList:未实例化

  • 这个回复+ 1; 非常有用,因为我想知道为什么eclipselink indirectlist isEmpty()出现在Java Visual VM中,因为我正在检查,比较和报告性能之后,只需检查列表!= null和!list.isEmpty替换indirectlist的JPA查询().这绝对解决了我遇到的性能问题; 最初访问数据库超过600次,但是使用最新的实现,只访问数据库5次! (3认同)
  • @gammay EclipseLink基于TopLink(fyi) (3认同)

Pio*_*cki 13

如果您{IndirectSet: not instantiated}在访问时获得的product.getOffers()可能性很大,那么您将在事务之外执行此代码.

默认情况下@OneToMany,@ManyToMany关系是延迟加载的,这意味着,为了获得更好的性能,只有在您第一次访问数据时才会获取数据.这必须在活动事务中发生.
如果您不在此范围内访问此数据,则无法再访问此数据.您应该将调用代码放在活动事务中,或者将集合更改为渴望而不是延迟:

@OneToMany(mappedBy="product", fetch=FetchType.EAGER)
Run Code Online (Sandbox Code Playgroud)


Arc*_*ano 6

这就是我做的

// force load of the set.
entity.getSecrets().isEmpty();
System.out.println(entity.getSecrets());
Run Code Online (Sandbox Code Playgroud)

  • 您可能会这么认为,但 EclipseLink 似乎没有这样做。无论如何,它可能是一个“功能”, .isEmpty() 强制设置加载我找到的。 (2认同)