私のテーブル:
製品: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:インスタンス化されていません}
これを修正する方法は?
これはnotエラーメッセージです。印刷命令の結果、toString()が基になる IndirectSet で呼び出されます。
TopLinkは、含まれているドメインオブジェクトがデータベースから読み取られるときに、インスタンス変数にIndirectSetを配置します。 IndirectSetに送信された最初のメッセージで、コンテンツがデータベースからフェッチされ、通常のSetの動作が再開されます。
IndirectCollection タイプは、toString()でインスタンス化されないように特別に実装されています。
デバッグの目的で、#toString()はデータベースの読み取りをトリガーしません。
ただし、size()やisEmpty()など、間接コレクションに対するその他の呼び出しは、オブジェクトをインスタンス化します。
データベースの読み取りは、「委任された」メソッドの1つがgetDelegate()を最初に呼び出したときに最終的にトリガーされ、次にbuildDelegate()が呼び出され、メッセージgetValue()が値の所有者に送信されます。値ホルダーはデータベースの読み取りを実行します。 IndirectSetに送信された最初のメッセージで、コンテンツがデータベースからフェッチされ、通常のSetの動作が再開されます。
product.getOffers()
にアクセスしたときに{IndirectSet: not instantiated}
を取得した場合は、おそらくトランザクションの外部でこのコードを実行しています。
デフォルトでは、@OneToMany
と@ManyToMany
の関係は 遅延読み込み です。つまり、パフォーマンスを向上させるために、初めてデータにアクセスする場合にのみデータがフェッチされます。これは、アクティブなトランザクション内で発生する必要があります。
このスコープ内でこのデータにアクセスしないと、このデータにアクセスできなくなります。呼び出しコードをアクティブなトランザクション内に配置するか、コレクションを怠惰ではなく eager に変更する必要があります。
@OneToMany(mappedBy="product", fetch=FetchType.EAGER)
これが私がしたことです
// force load of the set.
entity.getSecrets().isEmpty();
System.out.println(entity.getSecrets());
これで私の問題は解決しました
@OneToMany(mappedBy = "columnName"、cascade = {CascadeType.ALL}、fetch = FetchType.EAGER)
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;