web-dev-qa-db-ja.com

Hibernate:1対1の遅延読み込み、オプション= false

私は1対1の遅延読み込みが休止状態で動作しないという問題に直面しました。私はすでに解決しましたが、それでも適切にしないでくださいunderstand何が起こるか。

私のコード(遅延読み込みはここでは動作しません、Personを引っ張ると-アドレスも取得されます):

@Entity
public class Person{

  @Id
  @SequenceGenerator(name = "person_sequence", sequenceName = "sq_person")
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_sequence")
  @Column(name = "id")
  private long personID;

  @OneToOne(mappedBy="person", cascade=CascadeType.ALL, fetch = FetchType.LAZY)
  private Adress address;
  //.. getters, setters
}

@Entity
public class Address {

  @Id
  @Column(name="id", unique=true, nullable=false)
  @GeneratedValue(generator="gen")
  @GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="person"))
  private long personID;

  @PrimaryKeyJoinColumn
  @OneToOne
  private FileInfo person;
}

しかし():optional=falseOneToOne関係では、遅延読み込みは正常に動作します

@OneToOne(mappedBy="person", cascade=CascadeType.ALL, optional = false, fetch = FetchType.LAZY)
private Adress address;

質問/待遇:どうか教えてくださいoptional=false注釈は、遅延読み込みを実現するのに役立ちます。

PS投稿を読んだ post1 および post2 、そして単純なOneToOneができない理由を理解する怠beであるが、私はまだ把握できないoptional=false 魔法。

52
VB_

関連付けがオプションの場合、Hibernateはクエリを発行せずに特定の個人のアドレスが存在するかどうかを知る方法がありません。そのため、人を参照するアドレスが存在しないため、アドレスフィールドにプロキシを入力できません。また、人を参照するアドレスが存在する可能性があるため、nullを入力できません。

関連付けを必須にする場合(つまり、optional=false)、アソシエーションは必須なので、あなたを信頼し、アドレスが存在すると仮定します。そのため、アドレスフィールドにプロキシが直接入力され、その人物を参照するアドレスがあることがわかります。

77
JB Nizet

最も簡単な方法は、1対多の関係を偽造することです。これは、コレクションの遅延ロードが単一のnull可能プロパティの遅延ロードよりもはるかに簡単であるため機能しますが、一般に、このソリューションは複雑なJPQL/HQLクエリを使用する場合は非常に不便です。

もう1つは、ビルド時のバイトコードインストルメンテーションを使用することです。詳細については、Hibernateのドキュメントをご覧ください:19.1.7。遅延プロパティフェッチの使用。この場合、1対1の関係に@LazyToOne(LazyToOneOption.NO_PROXY)注釈を追加して遅延させる必要があることに注意してください。フェッチをLAZYに設定するだけでは不十分です。

最後の解決策は、ランタイムバイトコードインスツルメンテーションを使用することですが、本格的なJEE環境でJPAプロバイダーとしてHibernateを使用する場合にのみ機能します(このような場合は「hibernate.ejb.use_class_enhancer "を実行してトリックを実行する必要があります:エンティティマネージャーの構成)またはHibernateを実行時にウィービングを実行するように構成します(一部の古いアプリケーションサーバーではこれが難しい場合があります)。この場合@LazyToOne(LazyToOneOption.NO_PROXY)必須。

8
sendon1982