2012-03-10 70 views
1

我有責任準備報價搜索屏幕。我提到了Oracle觀點 來創建報價模型。由於view表中沒有id列,我更喜歡使用通過quoteId.class使用@IdClass註釋的複合id。我在兩個模型上重寫hashCode和equals方法。 quoteId等於&散列碼返回所有字段的組合並且引用散列碼&等於只是比較模型中的this.quoteNo字段。當我使用@IdClass LinkedHashSet包括重複的項目

報價模式:

@Override 
public int hashCode() 
{ 
    return new HashCodeBuilder(17,37) 
    .append(quoteNo) 
    .toHashCode(); 
} 

/* 
* (non-Javadoc) 
* 
* @see java.lang.Object#equals(java.lang.Object) 
*/ 
@Override 
public boolean equals(Object obj) 
{ 
    final quoteModel other = (quoteModel) obj; 
    return new EqualsBuilder().appendSuper(super.equals(other)) 
      .append(quoteNo, other.quoteNo).isEquals(); 
} 

當我需要獨特的項目,我只是通過訪問:

uniqueQuoteResults = new ArrayList<Quote>(
        new LinkedHashSet<Quote>(fullQuoteResults)); 

但是當我開始使用idClass我linkedHashSet擁有的所有項目,即使他們的報價數量相同。我是否缺少其他任何實現來證明每個項目的唯一性,通過引用沒有字段(比較,比較)?如果我跟蹤uniqueQuoteResult列表項值,它們都具有相同的報價編號。

編輯注意:我改變了我的方式使用Apache庫HashCodeBuilder和EqualsBuilder支持,但問題保持不變。恐怕idClass哈希碼的越來越有效linkedhashset

回答

2

有了下面的代碼在你的模型,你的測試是this.quoteNo同一個實例obj.quoteNo:

@Override 
public boolean equals(Object obj) 
{ 
    // TODO Auto-generated method stub 
    return this.quoteNo == ((EprocAwquoteV) obj).quoteNo; 
} 

結果是,與單獨構建的實例兩個實例的IdClass將被視爲不等於,如果quoteNo不是同一個對象。我猜你想測試quoteNo的平等,而不是用類似:

this.quoteNo.equals(other.quoteNo); 

也有一些其他的問題,在模型當前實現平等的(例如,它可以拋出ClassCastException異常)。基本原理可以從以下網址找到:Object.equalsOverriding the java equals() method quirk。 除了Hibernate之外,還有一點很重要,那就是你不應該測試類是否相同,而是使用instanceof(因爲代理類)。關於編寫的一些指令等於&實體的hascode可以從Hibernate documentation找到。

編輯: 您當前的方法是行不通的,因爲

return new EqualsBuilder().appendSuper(super.equals(other)) 

歸結下來的的Object.Equals。如果你沒有有意義的equals實現的超類。我不能完全確定我明白你的情況吧,所以也許你可以看看下面的工作實例,並找出的區別是:

public class QuoteId implements Serializable { 
    private int id1; 
    private int id2; 

    public QuoteId() {} 

    //This equals does not matter when we build LinkedHashSet 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     QuoteId other = (QuoteId) o; 
     return id1 == other.id1 && id2 == other.id2; 
    } 

    public int hashCode() { 
     return 31 * id1 + id2; 
    } 
} 

@Entity 
@IdClass(QuoteId.class) 
public class Quote { 
    @Id private int id1; 
    @Id private int id2; 
    String value; 

    public Quote() { 
    } 

    @Override 
    public boolean equals(Object o) { 
     if (this == o) return true; 
     if (o == null || getClass() != o.getClass()) return false; 
     Quote other = (Quote) o; 
     return id1 == other.id1 && id2 == other.id2; 
    } 

    @Override 
    public int hashCode() { return 31 * id1 + id2;} 

    //get&set for id1, id2, and value are omitted 
} 


tx.begin(); 
em.persist(new Quote(1, 1, "val")); 
em.persist(new Quote(1, 2, "val")); 
tx.commit(); 

TypedQuery<Quote> query = em.createQuery("SELECT q FROM Quote q", Quote.class); 
List<Quote> twoQuotes = query.getResultList();//both 

//duplicating (size=4) result for sake of test; 
List<Quote> fullQuoteResults = new ArrayList<Quote>(); 
fullQuoteResults.addAll(twoQuotes); 
fullQuoteResults.addAll(twoQuotes); 

//will have same elements as in twoQuotes: 
List<Quote> uniqueQuoteResults = new ArrayList<Quote>(
     new LinkedHashSet<Quote>(fullQuoteResults)); 
+0

嗨米克,謝謝你的回答,過了一會兒我已從Apache庫更改爲HashCodeBuilder和EqualsBuilder,但問題保持不變。今晚我會通過您的意見審查項目,並會更新我的問題。 – HRgiger 2012-03-13 09:27:40

+0

和+1對於很好的解釋:) – HRgiger 2012-03-13 09:35:45

+0

不客氣。你的當前版本的問題可能是:「新的EqualsBuilder()。appendSuper(super.equals(other)」。我猜你的quoteModel直接擴展了Object,並且像往常一樣,每個對象的實例都是不同的,你添加的其他東西甚至不會考慮到 – 2012-03-13 18:10:23