Java 当我使用@IdClass LinkedHashSet时,会包含重复项

Java 当我使用@IdClass LinkedHashSet时,会包含重复项,java,hibernate,jpa,linkedhashset,Java,Hibernate,Jpa,Linkedhashset,我的任务是准备报价搜索屏幕。我提到了Oracle视图 创建报价模型。由于视图表中没有id列,我更喜欢通过quoteId.class使用@IdClass注释来使用复合id。我在这两个模型上重写hashCode和equals方法。quoteId equals&hashcode返回所有字段的组合,quote hashcode&equals只需在模型中比较这个.quoteNo字段 报价模式: @Override public int hashCode() { return new HashCod

我的任务是准备报价搜索屏幕。我提到了Oracle视图 创建报价模型。由于视图表中没有id列,我更喜欢通过quoteId.class使用@IdClass注释来使用复合id。我在这两个模型上重写hashCode和equals方法。quoteId equals&hashcode返回所有字段的组合,quote hashcode&equals只需在模型中比较这个.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));
uniqueQuoteResults=newarraylist(
新LinkedHashSet(fullQuoteResults));
但当我开始使用idClass时,我的linkedHashSet拥有所有项目,甚至它们的报价编号都相同。我是否遗漏了通过quote no字段(Compariable,comparator)证明每个项目唯一性的任何其他实现?如果我跟踪uniqueQuoteResult列表项的值,则所有这些项都具有相同的报价编号


编辑说明:我已经改变了使用apache库HashCodeBuilder和EqualBuilder支持的方式,但问题仍然存在。我担心idClass hashcode会对linkedhashset生效,您测试的模型中有以下代码。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)。基本原则可从以下方面找到:和。 另外,对于Hibernate,重要的是要记住,您不应该测试类是否相同,而应该使用instanceof(因为代理类)。有关为实体编写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));
public类QuoteId实现可序列化{
私人int id1;
私有int id2;
公共QuoteId(){}
//当我们构建LinkedHashSet时,这并不重要
公共布尔等于(对象o){
如果(this==o)返回true;
如果(o==null | | getClass()!=o.getClass())返回false;
QuoteId其他=(QuoteId)o;
返回id1==other.id1&&id2==other.id2;
}
公共int hashCode(){
返回31*id1+id2;
}
}
@实体
@IdClass(QuoteId.class)
公开课报价{
@Id私有intid1;
@Id私有int id2;
字符串值;
公开报价(){
}
@凌驾
公共布尔等于(对象o){
如果(this==o)返回true;
如果(o==null | | getClass()!=o.getClass())返回false;
引用其他=(引用)o;
返回id1==other.id1&&id2==other.id2;
}
@凌驾
public int hashCode(){return 31*id1+id2;}
//忽略id1、id2和值的get&set
}
tx.begin();
em.persist(新报价(1,1,“val”);
em.persist(新报价(1,2,“val”);
tx.commit();
TypedQuery query=em.createQuery(“从Quote q中选择q”,Quote.class);
List twoQuotes=query.getResultList()//二者都
//复制(尺寸=4)结果以便测试;
List fullQuoteResults=new ArrayList();
fullQuoteResults.addAll(两个引号);
fullQuoteResults.addAll(两个引号);
//将具有与双引号中相同的元素:
List uniqueQuoteResults=新建ArrayList(
新LinkedHashSet(fullQuoteResults));

Hi Mikko,谢谢您的回答,过了一会儿,我从Apache库更改为HashCodeBuilder和EqualBuilder,但问题仍然存在。今晚我将通过你们的评论来回顾这个项目,并更新我的问题。欢迎你们。当前版本的问题可能是:“new EqualsBuilder().appendSuper(super.equals(other)”。我猜你的quoteModel直接扩展了Object,像往常一样,Object的每个实例都是不同的,你附加的其他东西甚至不会被考虑。可能是因为我没有正确地了解你案例的细节。也许你可以使用我添加到答案中的工作示例,找出差异所在。