簡體   English   中英

JPA / Hibernate:@ManyToOne和@OneToOne關系被標記為FetchType.LAZY,而Optional = false不能在em.find()上懶惰加載?

[英]JPA/Hibernate: @ManyToOne and @OneToOne relationships tagged as FetchType.LAZY and optional = false not loading lazily on 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;

    ...
}

請注意上面的注釋:與其他實體有三個@XToOne關系:

用戶 (具有簡單ID作為PK的SecurityIdentity子類,由PQ表示所有者):

@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>();

    ...
}

(也是具有簡單ID作為PK的SecurityIdentity子類,引用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實體上有三個@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=?

另外三個SELECT來自@XToOne關系(如網上許多地方所述)。 我看到的來源主要是這樣的:

使OneToOne關系變得懶惰

如前所述,不應提取@ManyToOne關系User user

@ManyToOne(fetch=FetchType.LAZY)應該可以正常工作。

...這里是從PQUser的關系,但是從select user0_.id as id280_0_, ...可以看到它 select user0_.id as id280_0_, ...語句...

對於另外兩個Group group和Tendering Tendering tendering ,兩個@OneToOne 反向映射,外鍵引用PQs表的PK(ID),導致PQ實體中的相同映射。

請注意,所有三個關系都不是可選的:PQ始終具有所有者(用戶),並且PQ始終由招標和組實體引用。 我剛才沒有在上面的JPA中建模......

因此,在將PQ實體的三個關系中添加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=?

注意,我只在PQ實體上使用optional = false ,因為這是我在em.find(...)使用的em.find(...) (如果這還不夠,請賜教。)

我現在的問題是雙重的:

  1. 為什么@ManyToOne急切地獲取User實體(鑒於據說這是懶惰的工作,請參閱使一個OneToOne關系變得懶惰 )?
  2. 為什么只有OneToOneTendering實體的關系不被提取? 是因為Tendering實體將PQ的PK列引用為PK本身( Tendering @Id ),而Group實體沒有(與PQ的PK有規律關系)?

怎么了? 如何使這些非可選關系變得懶惰? (沒有代碼檢測或其他黑客,只是簡單的注釋......)

我知道LAZY的事情只是提示JPA提供者做一些關於延遲加載的事情,但是在這種情況下,好像其他東西是錯誤的(因為它的一部分是有效的)。

PS:我正在使用Hibernate 4.0 BETA,JBoss 7.0.0.Final附帶的版本以及JPA注釋(以上都是JPA 1.0兼容)。

嗨,我不確定JPA,但對於many-to-oneone-to-one映射,支持hibernate的惰性值是proxyno-proxyfalse ,其中false是默認的。 檢查DTD的這一部分

lazy="proxy|no-proxy|false"

你可以查看這個鏈接 我認為這可以解決你的第一個問題。

使用hibernate注釋和jpa注釋之間存在差異,據我所知,除了某些情況外,hibernate默認是延遲加載的。 這是一個快速討論:

http://community.jboss.org/wiki/AShortPrimerOnFetchingStrategies

嗨Kawu你顯示額外的SELECT,因為它將為所有涉及的實體執行SELECTs,嘗試使用FetchType.LAZY默認為一對多,在大多數情況下使用FETCH JOIN來獲得結果。

我希望能幫助你或需要這些信息的人

* ToOne關系意味着在對象初始化之后必須有(代理)bean,一旦以任何方式訪問它就會觸發select(你看到它)你確定你對強制加載的對象什么都不做?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM