一对多关系不起作用

发布于 2024-12-18 13:57:44 字数 631 浏览 2 评论 0原文

我的表:

产品: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;
    ...
}

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

{IndirectSet:未实例化}

如何解决这个问题?

My Tables:

Product: id, name

Offer: id, value, product_id

Entities:

@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;
    ...
}

When I try to get some data from table Product, I get a java.lang.NullPointerException, and this code: product.getOffers() returns:

{IndirectSet: not instantiated}

How to fix this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

腻橙味 2024-12-25 13:57:44

不是错误消息。 print 指令导致在底层 间接设置

当 TopLink 会在实例变量中放置一个 IndirectSet
从数据库中读取包含域对象。与第一个
消息发送到IndirectSet,内容从
数据库和正常的 Set 行为已恢复。

IndirectCollection 类型专门实现为不实例化 toString()

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

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

当“委派”之一时,最终会触发数据库读取
方法首先调用 getDelegate(),后者依次调用
buildDelegate(),它将消息 getValue() 发送给值持有者。
值持有者执行数据库读取。与第一个
消息发送到IndirectSet,内容从
数据库和正常的 Set 行为已恢复。

另请参阅IndirectList:未实例化

This not an error message. The print instruction results in toString() being invoked on the underlying IndirectSet.

TopLink will place an IndirectSet in the instance variable when the
containing domain object is read from the datatabase. With the first
message sent to the IndirectSet, the contents are fetched from the
database and normal Set behavior is resumed.

IndirectCollection types are specifically implemented not to instantiate on toString():

For debugging purposes, #toString() will not trigger a database read.

However, any other call on the indirect collection, e.g., size() or isEmpty() will instantiate the object.

The database read is ultimately triggered when one of the "delegated"
methods makes the first call to getDelegate(), which in turn calls
buildDelegate(), which sends the message getValue() to the value holder.
The value holder performs the database read. With the first
message sent to the IndirectSet, the contents are fetched from the
database and normal Set behavior is resumed.

See also IndirectList: not instantiated

美人迟暮 2024-12-25 13:57:44

如果您在访问 product.getOffers() 时收到 {IndirectSet: not instantied} ,那么您很可能是在事务之外执行此代码。

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

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

If you get {IndirectSet: not instantiated} when accessing product.getOffers() than most probably you're executing this code outside of the transaction.

By default @OneToMany and @ManyToMany relationships are lazy loaded which means that, for better performance, you'll get data fetched only when you want to access it for the first time. This must happen within an active transaction.
If you don't access this data within this scope than you cannot access this data no more. You should either put your invocation code within the active transaction or change the collection to be eager instead of lazy:

@OneToMany(mappedBy="product", fetch=FetchType.EAGER)
你没皮卡萌 2024-12-25 13:57:44

这就是我所做的

// force load of the set.
entity.getSecrets().isEmpty();
System.out.println(entity.getSecrets());

Here's what I did

// force load of the set.
entity.getSecrets().isEmpty();
System.out.println(entity.getSecrets());
最笨的告白 2024-12-25 13:57:44

这解决了我的问题

@OneToMany(mappedBy = "columnName",cascade = { CascadeType.ALL}, fetch=FetchType.EAGER)

This solved my issue

@OneToMany(mappedBy = "columnName", cascade = { CascadeType.ALL}, fetch=FetchType.EAGER)

枫以 2024-12-25 13:57:44

我使用 Eclipselink 2.5.2 版本作为我的 ORM 供应商,并且在延迟加载包含实体时在一对多 JPA 映射中遇到了这个问题。对我有用的解决方法是: -

final List<ContainingEntity> list = Collections.unmodifiableList(new ArrayList<> 
                                    (containerEntity.getContainingEntityList());

从容器实体端的映射是:

@OneToMany(mappedBy = containerEntity, cascade = CascadeType.ALL, fetchType = FetchType.LAZY)
private List<ContainingEntity> containingEntityList;

从包含实体端的映射是:

@ManyToOne
@JoinColumn(name = "container_entity_id")
private ContainerEntity containerEntity;

I am using Eclipselink 2.5.2 version as my ORM vendor and I have faced this issue in one-to-many JPA mapping while lazy loading the containing entities. The workaround that is working for me is:-

final List<ContainingEntity> list = Collections.unmodifiableList(new ArrayList<> 
                                    (containerEntity.getContainingEntityList());

The Mapping from Container Entity side is:

@OneToMany(mappedBy = containerEntity, cascade = CascadeType.ALL, fetchType = FetchType.LAZY)
private List<ContainingEntity> containingEntityList;

Mapping from Containing Entity side is:

@ManyToOne
@JoinColumn(name = "container_entity_id")
private ContainerEntity containerEntity;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文