2010-06-29 39 views
5

Tôi hiện đang chuyển một ứng dụng (đang hoạt động) từ EclipseLink sang Hibernate JPA, chủ yếu là nó khá trơn tru, nhưng tôi đang tìm một thứ mà tôi không thể giải thích, và cũng có thể không nghĩ đến bất kỳ cụm từ tìm kiếm nào tốt!Hibernate JPA - Quan hệ ManyToOne không phổ biến

Về cơ bản, tôi có bốn đơn vị, với các mối quan hệ một-nhiều tạo thành một chuỗi:

EntityA có một danh sách các EntityB, mỗi trong số đó có một danh sách các EntityC, mỗi trong số đó có một danh sách EntityD của

mỗi người sau đó có nhiều-một mối quan hệ đi theo cách khác, vì vậy:

EntityD có EntityC, trong đó có một EntityB, trong đó có một EntityA.

Đó là (chủ yếu giảm cho rõ ràng):

@Entity 
public class EntityA { 
    @OneToMany (cascade = CascadeType.All, mappedBy = "entityA") 
    private List<EntityB> entityBList; 
    ... 
} 

@Entity 
public class EntityB { 
    @OneToMany (cascade = CascadeType.All, mappedBy = "entityB") 
    private List<EntityC> entityCList; 

    @JoinColumn (name = "ENTITY_A", referencedColumnName = "ENTITY_A_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityA entityA; 
} 

@Entity 
public class EntityC { 
    @OneToMany (cascade = CascadeType.ALL, mappedBy = "entityC") 
    private List<EntityD> entityDList; 

    @JoinColumn (name = "ENTITY_B", referencedColumnName = "ENTITY_B_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityB entityB; 
} 

@Entity 
public class EntityD { 
    @JoinColumn (name = "ENTITY_C", referencedColumnName = "ENTITY_C_ID") 
    @ManyToOne (cascade = CascadeType.PERSIST, optional = false) 
    private EntityC entityC; 
} 

tôi nhận được một EntityA từ cơ sở dữ liệu (nhìn nó lên bằng cách khóa chính của nó), và do đó có một trường hợp EntityA độc đáo dân cư, với một PersistentBag cho của tôi List<EntityB>. Tôi thấy một tải chậm xảy ra khi tôi dereference rằng List<EntityB>, và lặp đi lặp lại cùng nhau để nhận EntityCs từ EntityB. Tại thời điểm này, mọi thứ như tôi mong đợi, tôi có một EntityA, B và C tất cả được điền đầy đủ với các giá trị từ cơ sở dữ liệu, nhưng sau đó tôi cố gắng lấy EntityD của mình, từ EntityC, và thấy rằng nó không có giá trị.

Người quản lý đối tượng của tôi vẫn mở và hoạt động tại thời điểm này, và ngay cả khi tôi xem nó trong trình gỡ rối ngay sau khi nhận được EntityA, tôi có thể đi qua các mối quan hệ, đến tận EntityC, và một lần nữa xem 'entityDList 'là null.

Giải pháp duy nhất tôi đã tìm thấy cho đến nay là sử dụng:

EntityManager.refresh(entityC); 

mà populates tất cả các yếu tố của nó bao gồm một PersistentBag lười biếng-nạp cho entityDList. Vì vậy, tôi đoán là Hibernate chỉ điền các tham chiếu 2 cấp độ sâu (hoặc 3, tùy thuộc vào cách bạn đếm), và từ bỏ sau đó, mặc dù tôi không thực sự hiểu tại sao điều đó sẽ xảy ra. cái đó có phù hợp với ai không?

Có giải pháp nào khác ngoài .refresh không? Một số loại cấu hình hoặc giá trị chú thích mà sẽ làm cho Hibernate cư các tài liệu tham khảo tất cả các con đường xuống?

+0

Giá trị được đặt cho thông số cấu hình ngủ đông "max_fetch_depth" là gì? –

Trả lời

2

Nhờ những đề xuất từ ​​những người ở đây, có thể có liên quan nhưng không giúp trường hợp cụ thể của tôi.

Nếu bạn đang đọc trải nghiệm này, bạn nên thử đề xuất max_fetch_depth, nhưng vì lý do nào đó nó không hiệu quả đối với tôi (tôi muốn đề xuất là tại sao?). Tương tự như vậy, nếu OneToMany của bạn là Bộ, thay vì Danh sách, thực hiện tìm nạp háo hức hoặc tham gia trái, như đề xuất của Albert có thể hoạt động, nhưng dường như Hibernate chỉ cho phép bạn có tối đa 1 Danh sách được tìm nạp háo hức, nếu bạn cần nhiều hơn thế, bộ sưu tập của bạn phải là Bộ. Tôi đã không thử nó, nhưng tôi nghi ngờ rằng nó có thể giải quyết được vấn đề.

Trừ khi có ai đó có đề xuất tốt hơn, tôi sẽ kết hợp với tính năng gọi lại, điều này thực sự có ý nghĩa hơn đối với ứng dụng của tôi.

1

Điều này thật thú vị. Một cách để làm việc xung quanh nó sẽ là đối tượng truy vấn Một phép nối tham gia bên trái vào -> B-> C-> D cũng nhanh hơn nếu bạn đi ngang xuống đối tượng D. Nó sẽ là một cái gì đó như thế này.

"from A left join fetch B left join fetch C left join fetch D" 

Bạn cũng đã thử tạo mối quan hệ từ C-> D háo hức? Tò mò điều gì sẽ xảy ra sau đó ...

+0

Cảm ơn Albert, tôi đã thử cả hai đề xuất, không có kết quả: (Làm cho mối quan hệ háo hức không có hiệu lực, vì vậy tôi đã cố gắng tạo tất cả 3 mối quan hệ (A-> B-> C-> D) háo hức, nhưng Hibernate phàn nàn "không thể đồng thời Tìm thấy một cái gì đó khác cho thấy rằng đó là bởi vì các bộ sưu tập tôi đang háo hức lấy là Danh sách, và rằng nó sẽ làm việc nếu tôi làm cho họ Sets, nhưng Logged Tôi quá lười biếng để làm điều đó ngay bây giờ, vì vậy tôi nghĩ rằng tôi sẽ chỉ đưa ra một cuộc gọi làm mới! – DaveyDaveDave

1

Tài liệu ngủ đông nói rằng bạn có thể đặt nó với thuộc tính hibernate.max_fetch_depth. Mặc định là 3. Bạn có thể tìm thấy số này trong số "Hibernate Reference Documentation" trên trang 47.

+0

Cảm ơn điều này - bạn có biết nếu các tập tin hibernate.properties cũng được sử dụng bởi Hibernate JPA, tôi không thể tìm thấy Tôi đã cố gắng thay đổi nó đến 4 và cũng 0, và nó dường như không có hiệu lực ... – DaveyDaveDave

+0

OK, bỏ qua ở trên, nó dường như đang được sử dụng, bởi vì bằng cách thiết lập max_fetch_depth để 0 đã bị hỏng các phần khác của ứng dụng của tôi :) Đặt nó thành một số cao mặc dù (tôi đã thử 4 và 10), dường như không có bất kỳ ảnh hưởng nào; Tôi đoán bởi vì nó chỉ là một tối đa, và cái gì khác là thuyết phục Hibernate dừng lại ở 3 cấp độ ...? – DaveyDaveDave

Các vấn đề liên quan