web-dev-qa-db-ja.com

OneToMany関係が機能していません

私のテーブル:

製品:id、name

オファー: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;
    ...
}
_

テーブルProductからデータを取得しようとすると、_Java.lang.NullPointerException_が取得され、次のコードが返されます。product.getOffers()は次を返します。

{IndirectSet:インスタンス化されていません}

これを修正する方法は?

21
Emanuel

これはnotエラーメッセージです。印刷命令の結果、toString()が基になる IndirectSet で呼び出されます。

TopLinkは、含まれているドメインオブジェクトがデータベースから読み取られるときに、インスタンス変数にIndirectSetを配置します。 IndirectSetに送信された最初のメッセージで、コンテンツがデータベースからフェッチされ、通常のSetの動作が再開されます。

IndirectCollection タイプは、toString()でインスタンス化されないように特別に実装されています。

デバッグの目的で、#toString()はデータベースの読み取りをトリガーしません。

ただし、size()やisEmpty()など、間接コレクションに対するその他の呼び出しは、オブジェクトをインスタンス化します。

データベースの読み取りは、「委任された」メソッドの1つがgetDelegate()を最初に呼び出したときに最終的にトリガーされ、次にbuildDelegate()が呼び出され、メッセージgetValue()が値の所有者に送信されます。値ホルダーはデータベースの読み取りを実行します。 IndirectSetに送信された最初のメッセージで、コンテンツがデータベースからフェッチされ、通常のSetの動作が再開されます。

参照 IndirectList:インスタンス化されていません

26
Tomasz

product.getOffers()にアクセスしたときに{IndirectSet: not instantiated}を取得した場合は、おそらくトランザクションの外部でこのコードを実行しています。

デフォルトでは、@OneToMany@ManyToManyの関係は 遅延読み込み です。つまり、パフォーマンスを向上させるために、初めてデータにアクセスする場合にのみデータがフェッチされます。これは、アクティブなトランザクション内で発生する必要があります。
このスコープ内でこのデータにアクセスしないと、このデータにアクセスできなくなります。呼び出しコードをアクティブなトランザクション内に配置するか、コレクションを怠惰ではなく eager に変更する必要があります。

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

これが私がしたことです

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

これで私の問題は解決しました

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

0
Boris_Ndong

ORMベンダーとしてEclipselink2.5.2バージョンを使用していますが、含まれているエンティティの遅延読み込み中に1対多の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;
0
Arpa Mukherjee