Tôi đã thực thể sau (chỉ ánh xạ liên quan được hiển thị):JPA/Hibernate: @ManyToOne và @OneToOne mối quan hệ được gắn thẻ là FetchType.LAZY và tùy chọn = false không tải lazily trên 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;
...
}
Lưu ý các ý kiến trên: có ba @XToOne
mối quan hệ với các đơn vị khác:
tài (một lớp SecurityIdentity phụ với một đơn giản ID như PK, tham chiếu bởi PQ đại diện cho chủ sở hữu):
@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>();
...
}
Nhóm (một lso một tiểu lớp SecurityIdentity với một ID đơn giản như PK, tham chiếu PQ để đại diện cho một tập hợp các người dùng có thể tương tác với 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;
...
}
Đấu thầu:
@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;
...
}
Đừng nhầm lẫn giữa các nhóm và người dùng chia sẻ ID, chỉ coi họ là ID đơn giản. Đấu thầu chỉ là một đối tượng tài liệu riêng biệt (một đối một).
Như bạn có thể thấy có ba mối quan hệ @XToOne
trên thực thể PQ, trong đó, nếu không có loại tìm nạp nào được đặt, sẽ được tải háo hức (mặc định JPA). Vì vậy, để ngăn chặn điều này, tôi đã gắn thẻ tất cả các mối quan hệ @XToOne
là FetchType.LAZY
.
Bây giờ khi sử dụng
em.find(PQ.class, someExistingId);
tôi nhận được đầu ra 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=?
Ba lựa chọn thêm xuất phát từ các mối quan hệ @XToOne (như mô tả ở nhiều nơi trên mạng). Nguồn tôi đang tìm kiếm tại phần lớn là thế này:
Making a OneToOne-relation lazy
Như đã đề cập ở đó, các mối quan hệ @ManyToOne
User user
không nên lấy:
@ManyToOne(fetch=FetchType.LAZY)
nên chỉ làm việc tốt.
... đây mối quan hệ từ PQ để tài, nhưng nó là vời như bạn có thể nhìn thấy từ báo cáo kết quả select user0_.id as id280_0_, ...
...
Đối với hai người kia Group group
và Tendering tendering
, cả hai ánh sáng @OneToOne
đảo ngược ánh xạ, các khóa ngoại tham chiếu đến PK của bảng PQ (ID), dẫn đến ánh xạ giống nhau trong thực thể PQ.
Lưu ý rằng tất cả ba mối quan hệ không phải là tùy chọn: PQ luôn có chủ sở hữu (người dùng) và PQ luôn được tham chiếu bởi một thực thể đấu thầu và nhóm. Tôi vừa không mô hình hóa trong JPA ở trên ...
Vì vậy, khi thêm optional = false
với ba mối quan hệ của đối tượng PQ:
@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;
...
}
... Tôi nhận được đầu ra Hibernate sau:
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=?
Note, mà tôi đã chỉ được chơi với số optional = false
trên thực thể PQ, vì đây là số tôi sử dụng trong em.find(...)
. (Nếu đây là không đủ, xin soi sáng cho tôi.)
câu hỏi của tôi bây giờ là hai lần:
- Tại sao
@ManyToOne
để đơn vịUser
lấy háo hức (cho rằng là được cho là làm việc uể oải , xem Making a OneToOne-relation lazy)? - Tại sao chỉ quan hệ
OneToOne
với pháp nhânTendering
được tìm nạp? Có phải vì thực thểTendering
tham chiếu cột PK của PQ dưới dạng PK (@Id
trongTendering
), thực thểGroup
nào không (quan hệ thường xuyên với PK của PQ)?
Có vấn đề gì? Làm cách nào để làm cho các mối quan hệ không tùy chọn này trở nên lười biếng? (không có công cụ mã hóa hoặc các hack khác, chỉ là chú thích thuần túy ...)
Tôi biết điều LAZY chỉ là gợi ý cho nhà cung cấp JPA thực hiện điều gì đó về việc tải chậm hay không, nhưng trong trường hợp này có vẻ như cái gì khác là sai (như một phần của nó đang làm việc).
PS: Tôi đang sử dụng Hibernate 4.0 BETA, phiên bản đi kèm với JBoss 7.0.0.Final cùng với chú thích JPA chỉ (ở trên tất cả đều tương thích với JPA 1.0).
Có thể đó chỉ là lỗi. Xem https: // hibernate.onjira.com/browse/HHH-3930, tương tự. –