2014-11-05 19 views
8

Tôi đang gặp phải sự cố lạ khi sử dụng JPA/Hibernate. Tôi thấy các mục trùng lặp trong quá trình thử nghiệm.Lấy mục nhập trùng lặp bằng cách sử dụng Hibernate

Đây là lớp BaseEntity tôi:

@Entity 
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 
public abstract class BaseEntity { 

    @Id 
    @Column(name = "ID", updatable = false, nullable = false) 
    @GenericGenerator(name = "uniqueIDGenerator", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", parameters = { 
      @org.hibernate.annotations.Parameter(name = "sequence_name", value = "ID_SEQUENCE"), 
      @org.hibernate.annotations.Parameter(name = "increment_size", value = "100"), 
      @org.hibernate.annotations.Parameter(name = "optimizer ", value = "pooled") }) 
    @GeneratedValue(generator = "uniqueIDGenerator") 
    @NotNull 
    protected int id; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

} 

Đây là chính lớp đối tác của tôi:

@Entity 
@Table(name = "partner") 
public class Partner extends BaseEntity{ 

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

    @OneToMany(mappedBy="partner", fetch=FetchType.EAGER) 
    @Cascade(CascadeType.DELETE) 
    private List<Receipt> receipts; 

    @OneToMany(mappedBy="partner", fetch=FetchType.EAGER) 
    @Cascade(CascadeType.DELETE) 
    private List<Delivery> deliveries; 

    public Partner() { 
     setReceipts(new ArrayList<Receipt>()); 
     setDeliveries(new ArrayList<Delivery>()); 
    } 

    public Partner(String name){ 
     this(); 

     this.setName(name); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public List<Receipt> getReceipts() { 
     return receipts; 
    } 

    public void setReceipts(List<Receipt> receipts) { 
     this.receipts = receipts; 
    } 

    public List<Delivery> getDeliveries() { 
     return deliveries; 
    } 

    public void setDeliveries(List<Delivery> deliveries) { 
     this.deliveries = deliveries; 
    } 
} 

Đối tác có hai lớp con, nghiệm thu, bàn giao hàng. Đây là lớp nhận:

@Entity 
@Table(name = "receipt") 
public class Receipt extends BaseEntity{ 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="partnerId") 
    private Partner partner; 

    @Column(name = "name") 
    private String name; 
    @Column(name = "json") 
    private String json; 

    @Transient 
    private ReceiptContainer receiptContainer; 


    public Receipt() { 
    } 
    public Receipt(String name){ 
     this(); 

     this.setName(name); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getJson() { 
     return json; 
    } 

    public void setJson(String json) { 
     this.json = json; 
    } 

    public ReceiptContainer getReceiptContainer() { 
     return receiptContainer; 
    } 

    public void setReceiptContainer(ReceiptContainer receiptContainer) { 
     this.receiptContainer = receiptContainer; 
    } 

    public Partner getPartner() { 
     return partner; 
    } 

    public void setPartner(Partner partner) { 
     this.partner = partner; 
    } 

} 

đây là lớp giao hàng:

@Entity 
@Table(name = "delivery") 
public class Delivery extends BaseEntity{ 

    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="partnerId") 
    private Partner partner; 

    @Column(name = "name") 
    private String name; 
    @Column(name = "json") 
    private String json; 

    @Transient 
    private DeliveryContainer deliveryContainer; 


    public Delivery() { 
    } 
    public Delivery(String name){ 
     this(); 

     this.setName(name); 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getJson() { 
     return json; 
    } 

    public void setJson(String json) { 
     this.json = json; 
    } 

    public DeliveryContainer getDeliveryContainer() { 
     return deliveryContainer; 
    } 

    public void setDeliveryContainer(DeliveryContainer deliveryContainer) { 
     this.deliveryContainer = deliveryContainer; 
    } 

    public Partner getPartner() { 
     return partner; 
    } 

    public void setPartner(Partner partner) { 
     this.partner = partner; 
    } 

} 

Tôi nhận đối tượng của tôi như thế này:

@Transactional 
public Partner get(int id){ 
    Partner partner = entityManager.find(Partner.class, id); 
    return partner; 
} 

Như bạn có thể thấy, lớp đối tác bao gồm Danh sách các đối tượng và Danh sách các đối tượng, được lưu trữ trong bảng, nhận và phân phối riêng của chúng, tương ứng.

--- Trước khi tôi đi xa hơn, tôi muốn lưu ý rằng con số chính xác các mục được hiển thị trong cơ sở dữ liệu. Vấn đề này chỉ xảy ra khi nhận các đối tượng trong ứng dụng Java của tôi .---

Khi tôi thêm một đối tượng và không có đối tượng nào, một đối tượng được hiển thị và không có đối tượng nào được hiển thị. Nếu một đối tượng và một đối tượng tồn tại, một đối tượng và một đối tượng được hiển thị, một lần nữa, được mong đợi. Vấn đề xảy ra khi có nhiều hơn một đối tượng. Ví dụ, nếu hai đối tượng được thêm vào nhưng chỉ có một đối tượng được thêm vào, hai đối tượng VÀ hai đối tượng được hiển thị.

Để minh hoạ rõ hơn điều này, xem bảng test của tôi dưới đây. Kết quả bất ngờ được bao quanh với dấu gạch ngang.

<Receipt> Obj Added | <Delivery> Obj Added | <Receipt> Obj Displayed | <Delivery> Obj Displayed 
     0   |   0   |   0    |   0 
     0   |   1   |   0    |   1 
     1   |   0   |   1    |   0 
     1   |   1   |   1    |   1 
     1   |   2   |  ---2---   |   ---2--- 
     2   |   1   |  ---2---   |   ---2--- 
     2   |   2   |  ---4---   |   ---4--- 

Câu hỏi của tôi là, tại sao tôi thấy những kết quả không mong muốn này?

+0

Cần một vài mẩu hơn về thông tin để giúp: hiển thị như thế nào bạn đang tạo ID cho các lớp này (gửi lớp BaseEntity của bạn), cho thấy làm thế nào bạn đang kiên trì và lấy dữ liệu – zmf

+0

Chỉ cần thêm, nhờ – user1472409

Trả lời

10

Lý do bạn đang nhìn thấy bản sao là bởi vì bạn đang háo hức lấy các em, mà đang tạo ra một bên ngoài tham gia.

(Bạn có thể sử dụng @Fetch (FetchMode.SELECT), nhưng điều này sẽ cho kết quả truy vấn bổ sung để lấy các mục của bạn)

Hibernate API reference indicating outer join takes place.

Dưới đây là một trong câu trả lời sâu cho câu hỏi của bạn: Hibernate Criteria returns children multiple times with FetchType.EAGER

Bạn có thể chuyển từ Danh sách để Set (hãy chắc chắn bạn ghi đè bằng/compareTo/hashCode nếu bạn làm như vậy). Hoặc bạn có thể thêm bộ biến đổi kết quả vào kết quả truy vấn của mình nếu bạn trích xuất các mục này từ cơ sở dữ liệu qua tiêu chí.

Đối với những gì giá trị của nó, Hibernate khuyến cáo sử dụng bộ trên danh sách

+0

ai đó nên sử dụng Danh sách hoặc Đặt dựa trên việc họ muốn Danh sách hoặc Đặt ngữ nghĩa, không dựa trên việc liệu một số giải pháp kiên trì "đề xuất" một. Các giải pháp kiên trì nên minh bạch cho tất cả mọi thứ –

+0

Đó có phải là một lời chỉ trích của đề nghị của tôi để sử dụng bộ, hoặc ngủ đông? – zmf

+0

Đó là một tuyên bố đơn giản về lý do tại sao bất kỳ nhà phát triển nào nên chọn một loại Bộ sưu tập cụ thể - lựa chọn giải pháp kiên trì không được đưa vào đối số, chỉ có mô hình. Nếu mọi người chọn coi đó là "phê bình" thì tùy thuộc vào họ –

6

lẽ bạn có thể thử làm truy vấn của bạn sử dụng tài sản DISTINCT.

Đơn giản chỉ cần thêm video này vào tiêu chí của bạn:

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

Nếu bạn không sử dụng các tiêu chí:

SELECT DISTINCT <QUERY> 

Nếu nó không giải quyết được vấn đề của bạn, hiển thị mã truy vấn của bạn.

0

Bạn có thể lưu trữ các kết quả của truy vấn của bạn trong một Set, nó sẽ loại bỏ trùng lặp cho bạn.

0

Nếu bạn đang sử dụng JPA:

CriteriaBuilder cb = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Receipt> query = cb.createQuery(Receipt.class); 
query.distinct(true); 

khác xem câu trả lời Gernan của.

0

Hibernate không trả về kết quả riêng biệt cho truy vấn có tìm nạp tham gia bên ngoài được bật cho bộ sưu tập (ngay cả khi tôi sử dụng từ khóa riêng biệt)? đọc more, nó có thể giúp bạn ..

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