когда я использую @IdClass LinkedHashSet включать дубликаты - PullRequest
1 голос
/ 11 марта 2012

Мне поручено подготовить экран поиска цитаты.Я сослался на представление Oracle для создания модели котировок.Поскольку в таблице представлений нет столбца id, я предпочитаю использовать составной идентификатор, используя аннотацию @IdClass через quoteId.class.Я переопределяю hashCode и метод equals в обеих моделях.quoteId equals & hashcode возвращает комбинацию всех полей и кавычки hashcode & equals просто сравните поле this.quoteNo в модели.

Quote quote:

@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, мой connectedHashSet содержит все элементы, даже их номер кавычки.Я пропускаю какую-либо другую реализацию, чтобы доказать уникальность каждого элемента через кавычку без поля (сопоставимый, компаратор)?Если я отслеживаю значения элементов списка uniqueQuoteResult, все они имеют одинаковый номер кавычки.

Редактировать Примечание: Я изменил свой способ использования поддержки Apache HashCodeBuilder и EqualsBuilder, но проблема остается той же.Я боюсь, что хеш-код idClass становится эффективным для связанного хэш-набора

1 Ответ

2 голосов
/ 11 марта 2012

Используя следующий код в вашей модели, вы проверяете this.quoteNo тот же экземпляр, что и obj.quoteNo:

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

Результатом является то, что два экземпляра с отдельно созданным экземпляром IdClass будут считаться не равными, если quoteNo не является одним и тем же объектом. Я думаю, что вы хотите проверить равенство quoteNo's вместо этого что-то вроде:

this.quoteNo.equals(other.quoteNo);

Также есть некоторые другие проблемы с текущей реализацией equals в модели (например, это может вызвать ClassCastException). Основные принципы можно найти в следующих статьях: Object.equals и Переопределение метода java equals () quirk . Кроме того, в Hibernate важно помнить, что вы не должны тестировать классы одинаково, а вместо этого использовать instanceof (из-за прокси-классов). Некоторые инструкции по написанию equals & hascode для сущностей можно найти в Документация Hibernate .

EDIT: Ваш текущий подход не работает, потому что

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