2011-10-11 28 views
15

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ệ @XToOneFetchType.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ệ @ManyToOneUser 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ó 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 groupTendering 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:

  1. 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)?
  2. Tại sao chỉ quan hệ OneToOne với pháp nhân Tendering đượ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 trong Tendering), 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).

+0

Có thể đó chỉ là lỗi. Xem https: // hibernate.onjira.com/browse/HHH-3930, tương tự. –

Trả lời

2

Hi Tôi không chắc chắn về JPA, nhưng đối với many-to-oneone-to-one ánh xạ các giá trị lười biếng được hỗ trợ chế độ ngủ đông là proxy, no-proxyfalse trong đó sai được mặc định. kiểm tra phần này của DTD

lazy="proxy|no-proxy|false"

và bạn có thể kiểm tra Link này. Tôi nghĩ rằng điều này trả lời câu hỏi đầu tiên của bạn để mở rộng.

+0

Mặc định cho 'lazy =" proxy | no-proxy | false "' là proxy, như được viết trong liên kết bạn đã đăng (xem 12): "lười (tùy chọn - mặc định thành proxy): theo mặc định, các liên kết điểm đơn lazy = "no-proxy" chỉ định rằng thuộc tính sẽ được tải xuống một cách lười biếng khi biến cá thể được truy cập lần đầu. Điều này đòi hỏi công cụ bytecode xây dựng theo thời gian. – Kawu

0

* Mối quan hệ ToOne ngụ ý rằng phải có (proxy) bean sau khi khởi tạo đối tượng, sẽ kích hoạt lựa chọn (bạn thấy nó) ngay sau khi được truy cập theo bất kỳ cách nào bạn chắc chắn bạn không làm gì với các đối tượng có thể bắt buộc tải?

0

Hi Kawu bạn hiển thị lựa chọn thêm vì nó sẽ thực hiện lựa chọn cho tất cả các đơn vị tham gia, hãy thử sử dụng FetchType.LAZY cho mặc định One-to-Nhiều và trong nhiều trường hợp để sử dụng Fetch THAM GIA để có được kết quả.

Tôi hy vọng sẽ giúp bạn hoặc ai đó cần thông tin này