2011-10-11 18 views
15

私は、次のエンティティ(のみ関係マッピングが示す)持っている:JPA/Hibernate:@ManyToOneと@OneToOneの関係はFetchType.LAZYとタグ付けされ、オプション= falseはem.find()に遅れてロードされませんか?

@Entity 
@Table(name = "PQs") 
public class PQ implements Serializable 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column 
    private Integer id; 

    @Column 
    private String name; 

    @ManyToOne(fetch = FetchType.LAZY)     // lazy XToOne 
    @JoinColumn(name = "user_id", referencedColumnName = "person_id") 
    private User user; 

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) // lazy XToOne 
    private Group group; 

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY) // lazy XToOne 
    private Tendering tendering; 

    ... 
} 

注上記のコメントを:

ユーザー(でSecurityIdentityサブクラスシンプルで:他のエンティティへの3人の@XToOne関係があります所有者)を表すPQによって参照PKとしてID:

@Entity 
@Table(name = "Users") 
@DiscriminatorValue(value = "user") 
public class User extends SecurityIdentity 
{ 
    @Column 
    private String name; 

    @OneToMany(mappedBy = "user") 
    private Set<PQ> pqs = new HashSet<PQ>(); 

    ... 
} 

グループを(A PKのような単純なIDを持つでSecurityIdentityサブクラスLSO、)そのPQと対話することができ、ユーザーの集合を表すためにPQを参照:を入札

@Entity 
@Table(name = "Groups") 
@DiscriminatorValue(value = "group") 
public class Group extends SecurityIdentity 
{ 
    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "pq_id", referencedColumnName = "id") 
    private PQ pq; 

    ... 
} 

@Entity 
@Table(name = "Tenderings") 
public class Tendering implements Serializable 
{ 
    @Id 
    @Column(name = "pq_id", insertable = false, updatable = false) 
    private Integer pqId; 

    @Column(name = "external_code") 
    private String externalCode; 

    @OneToOne(fetch = FetchType.LAZY) 
    @JoinColumn(name = "pq_id", referencedColumnName = "id") 
    private PQ pq; 

    ... 
} 

しないでくださいグループとユーザーがIDを共有するのを混乱させて、単純なIDとして扱うだけです。入札は単なる別のドキュメントオブジェクト(一対一)です。

PQエンティティには3つの@XToOneリレーションシップがあります。フェッチタイプが設定されていない場合は、熱心に読み込まれます(JPAデフォルト)。だから私はこれを防ぐために@XToOneの関係をFetchType.LAZYとタグ付けしました。今

em.find(PQ.class, someExistingId);

を使用して、私はHibernateの出力が得られます(ネット上の多くの場所で説明したように)

23:53:55,815 INFO [stdout] Hibernate: select pq0_.id as id291_0_, pq0_.description as descript2_291_0_, pq0_.name as name291_0_, pq0_.submission_date as submission4_291_0_, pq0_.user_id as user5_291_0_ from PQs pq0_ where pq0_.id=? 
23:53:55,818 INFO [stdout] Hibernate: select user0_.id as id280_0_, user0_1_.identity_type_id as identity2_280_0_, user0_.is_enabled as is1_297_0_, user0_.name as name297_0_, user0_.password as password297_0_, user0_.person_id as person5_297_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=? 
23:53:55,821 INFO [stdout] Hibernate: select group0_.id as id280_0_, group0_1_.identity_type_id as identity2_280_0_, group0_.pq_id as pq2_281_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=? 
23:53:55,823 INFO [stdout] Hibernate: select tendering0_.pq_id as pq1_296_0_, tendering0_.binary_file as binary2_296_0_, tendering0_.customer_id as customer6_296_0_, tendering0_.description as descript3_296_0_, tendering0_.external_code as external4_296_0_, tendering0_.title as title296_0_ from Tenderings tendering0_ where tendering0_.pq_id=? 

3つの余分のSELECTは@XToOne関係から生じます。私はほとんど見ていたソースはこれです:そこに述べたように

Making a OneToOne-relation lazy

@ManyToOne関係User userがフェッチすべきではない:

@ManyToOne(fetch=FetchType.LAZY)はうまく動作するはずです。あなたはselect user0_.id as id280_0_, ...の文から見ることができるよう

が...ここPQユーザーへの関係が、それは、他の2つのGroup groupTendering tenderingについては

...フェッチされ、両方とも@OneToOneマッピングの場合、外部キーはPQエンティティで同じマッピングをもたらすPQテーブルのPK(ID)を参照します。

3つの関係はすべてオプションではないことに注意してください.PQは常に所有者(ユーザー)を持ち、PQは常に入札およびグループエンティティによって参照されます。私はちょうど上記のJPAでそれをモデル化していなかった...

PQエンティティの3つの関係にoptional = falseを追加するときに、:

@Entity 
@Table(name = "PQs") 
public class PQ implements Serializable 
{ 
    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    @Column 
    private Integer id; 

    @Column 
    private String name; 

    @ManyToOne(fetch = FetchType.LAZY, optional = false) 
    @JoinColumn(name = "user_id", referencedColumnName = "person_id") 
    private User user; 

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false) 
    private Group group; 

    @OneToOne(mappedBy = "pq", fetch = FetchType.LAZY, optional = false) 
    private Tendering tendering; 

    ... 
} 

...私は、次のHibernateの出力を得る:私はしてきたことを

00:47:34,397 INFO [stdout] Hibernate: select pq0_.id as id361_0_, pq0_.description as descript2_361_0_, pq0_.name as name361_0_, pq0_.submission_date as submission4_361_0_, pq0_.user_id as user5_361_0_ from PQs pq0_ where pq0_.id=? 
00:47:34,410 INFO [stdout] Hibernate: select user0_.id as id350_0_, user0_1_.identity_type_id as identity2_350_0_, user0_.is_enabled as is1_367_0_, user0_.name as name367_0_, user0_.password as password367_0_, user0_.person_id as person5_367_0_ from Users user0_ inner join SecurityIdentities user0_1_ on user0_.id=user0_1_.id where user0_.person_id=? 
00:47:34,413 INFO [stdout] Hibernate: select group0_.id as id350_0_, group0_1_.identity_type_id as identity2_350_0_, group0_.pq_id as pq2_351_0_ from Groups group0_ inner join SecurityIdentities group0_1_ on group0_.id=group0_1_.id where group0_.pq_id=? 

注意、これはem.find(...)で使用しているので、PQエンティティのoptional = falseで再生しています。 (これが十分でない場合は、私を啓発してください。)

私の質問は今二つある:

  1. Userエンティティへ@ManyToOneですがいい加減に仕事ができると言われたことを考えると(熱心にフェッチされるのはなぜ、Making a OneToOne-relation lazyを参照)?
  2. はなぜTenderingエンティティにのみOneToOne関係がフェッチされてオフ残っていますか?それはTenderingエンティティがGroup実体がないPK自体(Tendering@Id)としてPQのPK列、(PQのPKへの定期的な関係)を参照しているためですか?

は何が悪いのでしょうか?これらの非オプションの関係を怠惰にするにはどうすればよいですか?

私は、LAZYのことは、JPAプロバイダがレイジーローディングについて何かをするためのヒントであることは知っていますが、この場合はまるでそうであるように見えます他の何かが間違っている(その一部が機能している)。

PS:私はJBoss 7.0.0.Finalに付属しているバージョンで、JPAアノテーションのみでHibernate 4.0 BETAを使用しています(上記はすべてJPA 1.0と互換性があります)。

+0

これは単なるバグです。 https:// hibernateを参照してください。onjira.com/browse/HHH-3930、それは似ています。 –

答えて

2

こんにちは私はJPAについてはわからないが、many-to-oneone-to-oneマッピングのために休止状態をサポートしている怠惰な値がproxyno-proxyfalseデフォルト設定されている偽のアウトをしています。 DTD

lazy="proxy|no-proxy|false"

のこの部分をチェックして、あなたはこのLinkを確認することができます。私はこれがあなたの最初の質問に答えてくれると思います。

+0

'lazy =" proxy | no-proxy | false "'のデフォルトは、あなたが投稿したリンク(12を参照)で書かれているようにプロキシです: "lazy(オプション - デフォルトはプロキシ) lazy = "no-proxy"は、インスタンス変数が最初にアクセスされたときにプロパティを遅延的にフェッチするように指定します。 – Kawu

0

* ToOneの関係は、オブジェクトの初期化後に(プロキシ)Beanが必要であることを意味します。これは、何らかの方法でアクセスされるとすぐに選択(あなたが見ている)を引き起こします。読み込み中ですか?

0

こんにちはKawuそれは、すべての関与するエンティティのためのSELECTを実行するデフォルトの一対多のためFetchType.LAZYを使用して試してみて、ほとんどの場合、そう、JOIN FETCHを使用しますので、あなたが余分なのSELECTを表示します結果を得る。

私はこの情報が必要な人を助けることを願っています。

関連する問題