一对多关系不起作用

2022-09-02 02:53:49

我的表:

产品:ID、名称

报价:id、值、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;
    ...
}

当我尝试从表中获取一些数据时,我得到一个,并且此代码:返回:Productjava.lang.NullPointerExceptionproduct.getOffers()

{间接集:未实例化}

如何解决这个问题?


答案 1

这不是一条错误消息。打印指令导致在基础间接集上调用 toString()。

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

间接集合类型专门实现为不在 toString() 上实例化:

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

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

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

另请参见间接列表:未实例化


答案 2

如果你在访问时得到比很可能你正在事务之外执行此代码。{IndirectSet: not instantiated}product.getOffers()

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

@OneToMany(mappedBy="product", fetch=FetchType.EAGER)

推荐