2014-11-05 90 views
8

使用JPA/Hibernate時遇到了一個奇怪的問題。我在測試過程中看到重複的條目。使用休眠獲取重複條目

這裏是我的BaseEntity類:

@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; 
    } 

} 

這是我的主要合作伙伴等級:

@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; 
    } 
} 

合作伙伴有兩個子類,收據和交付。這是發票類:

@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; 
    } 

} 

這裏是交貨類:

@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; 
    } 

} 

我收到我的對象是這樣的:

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

正如你可以看到,夥伴類包括對象列表和對象列表,它們分別存儲在它們自己的表格,收據和傳送中。

---我再往前走之前,我想指出的是項目的正確號碼顯示在數據庫中。只有在我的Java應用程序.---獲取對象時出現此問題

當我添加一個對象,沒有對象都存在,則顯示一個對象,並沒有顯示任何對象,預計。如果存在一個對象和一個對象,則再次顯示一個對象和一個對象,這是預期的。如果存在多個對象或對象,則會出現該問題。例如,如果添加兩個對象,但只添加一個對象,則會顯示兩個對象和兩個對象。

爲了更好地說明這一點,請參閱下面我的測試情況表。意外的結果被用破折號包圍。

<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--- 

我的問題是,爲什麼我看到這些意外的結果?

+0

需要幾個信息來幫助:顯示你如何爲這些類生成ID(發佈你的baseentity類),顯示你如何持久化和檢索數據 – zmf 2014-11-05 17:23:53

+0

剛剛添加,謝謝 – user1472409 2014-11-05 17:45:54

回答

10

你看到重複的原因是因爲你急切地獲取的兒童,這是建立一個外部聯接。

(你可以使用@Fetch(FetchMode。SELECT),但是這會導致額外的查詢檢索您的項目)

Hibernate API reference indicating outer join takes place.

這裏是一個深入回答你的問題:Hibernate Criteria returns children multiple times with FetchType.EAGER

您可以從列表開關設置(請確認您如果你這樣做,覆蓋equals/compareTo/hashCode)。或者,如果要通過條件從數據庫中提取這些項目,則可以將結果轉換器添加到查詢結果中。

對於它的價值,休眠建議如果你正在使用JPA使用套在列表

+0

有人應該使用List或Set,基於他們是否想要List或Set語義,而不是基於某個持久性解決方案是否「推薦」一個。持久性解決方案應該對所有東西都是透明的 – 2014-11-05 18:08:43

+0

這是對我推薦使用set或hibernate的批評嗎? – zmf 2014-11-05 19:25:44

+0

這是一個簡單的陳述,說明爲什麼任何開發人員都應該選擇一個特定的集合類型 - 持久性解決方案的選擇不應該進入參數,只有模型。如果人們選擇把它作爲「批評」取決於他們 – 2014-11-06 06:36:07

6

也許你可以嘗試使用DISTINCT屬性來進行查詢。如果你不使用標準

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

只需添加到您的標準

SELECT DISTINCT <QUERY> 

如果不解決您的問題,顯示你的查詢代碼。

0

你可以存儲在一個Set您的查詢的結果,它會刪除重複的爲您服務。

0

什麼:

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

否則看到Gernan的答案。

0

對於爲集合啓用外部聯接抓取的查詢,Hibernate不會返回不同的結果(即使我使用distinct關鍵字)?閱讀more,它可能會幫助你..