【问题标题】:when I use @IdClass LinkedHashSet include duplicate items当我使用@IdClass LinkedHashSet 时包含重复项
【发布时间】:2012-03-10 22:26:43
【问题描述】:

我的任务是准备一个报价搜索屏幕。我提到了一个 Oracle 视图 创建报价模型。由于视图表中没有 id 列,我更喜欢通过 quoteId.class 使用 @IdClass 注释来使用复合 id。我在两个模型上都覆盖了 hashCode 和 equals 方法。 quoteId equals & hashcode 返回所有字段的组合,quote hashcode & equals 只是比较模型中的 this.quoteNo 字段。

报价模型:

@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 生效

【问题讨论】:

    标签: java hibernate jpa linkedhashset


    【解决方案1】:

    在您的模型中使用以下代码,您测试的是 this.quoteNo 与 obj.quoteNo 相同的实例:

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

    结果是,如果quoteNo不是同一个对象,两个实例分别构造的IdClass实例将被认为不相等。我猜你想用类似的东西来测试quoteNo的相等性:

    this.quoteNo.equals(other.quoteNo);
    

    目前模型中的equals实现还有一些其他问题(例如它可以抛出ClassCastException)。基本原理可参考:Object.equalsOverriding the java equals() method quirk。 此外,对于 Hibernate,重要的是要记住,您不应该测试类相同,而是使用 instanceof(因为代理类)。可以从Hibernate documentation 找到一些关于为实体编写 equals&hascode 的说明。

    编辑: 您当前的方法不起作用,因为

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

    【讨论】:

    • 嗨 Mikko,谢谢你的回答,过了一段时间我已经从 Apache 库更改为 HashCodeBuilder 和 EqualsBuilder 但问题仍然存在。今晚我将通过您的 cmets 审查项目并更新我的问题。
    • 不客气。您当前版本的问题很可能是:“new EqualsBuilder().appendSuper(super.equals(other)”。我猜您的 quoteModel 直接扩展 Object 并且像往常一样,对象的每个实例都是不同的,您附加的其他内容甚至不会考虑。
    • 可能是我没有正确了解您的情况。也许您可以使用我添加到答案中的工作示例并找出差异在哪里。
    猜你喜欢
    • 2019-05-12
    • 1970-01-01
    • 2014-08-26
    • 2019-10-31
    • 1970-01-01
    • 2019-01-27
    • 2013-08-30
    • 2021-09-29
    • 2011-09-25
    相关资源
    最近更新 更多