Хеш-код BigInteger для встраиваемого составного ключа

1

У меня есть двухколоночный первичный ключ в базе данных, который мне нужно моделировать с помощью приложения mvc spring, использующего hibernate 4.2 и jpa. Из того, что я читал в Интернете, кажется, что мой составной ключевой класс ConceptPK должен включать в себя метод hashcode. Проблема в том, что одним из двух элементов первичного ключа является тип данных BigInteger, но тип возвращаемого по умолчанию метода hashcode() - int. Это заставляет eclipse давать сообщение об ошибке ниже, указывающее, что программа не будет компилироваться, потому что у меня неправильный тип возврата для метода hashcode.

Мне нужен метод hashcode? И что мне нужно сделать с приведенным ниже кодом, чтобы заставить его скомпилировать с правильно функционирующим составным ключом ConceptPK?

import java.io.Serializable;
import java.math.BigInteger;
import javax.persistence.Column;
import javax.persistence.Embeddable;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;

@Embeddable
class ConceptPK implements Serializable {

@Column(name="id", nullable=false)
protected BigInteger id;

@Column(name="effectiveTime", nullable=false)
@Type(type="org.jadira.usertype.dateandtime.joda.PersistentDateTime")
private DateTime effectiveTime;

public ConceptPK() {}
public ConceptPK(BigInteger bint, DateTime dt) {
    this.id = bint;
    this.effectiveTime = dt;
}

/** getters and setters **/
public DateTime getEffectiveTime(){return effectiveTime;}
public void setEffectiveTime(DateTime ad){effectiveTime=ad;}

public void setId(BigInteger id) {this.id = id;}
public BigInteger getId() {return id;}

public boolean equals(Object o) { 
    return ((o instanceof ConceptPK) && 
            effectiveTime.equals(((ConceptPK)o).getEffectiveTime()) &&
            id == ((ConceptPK) o).getId());
}

public int hashCode() { 
    BigInteger sum = BigInteger.valueOf(
            effectiveTime.hashCode()
            );
    sum.add(id); 
    return sum;//this line has error message indicating wrong return data type
}
}  

Вот код для класса, который использует ConceptPK в качестве первичного ключа:

@Entity
@Table(name = "tablename")
public class Concept implements Serializable{

    @EmbeddedId
    @AttributeOverrides({
        @AttributeOverride(name="id", column=@Column(name="id")),
        @AttributeOverride(name="effectiveTime", column=@Column(name="effectiveTime"))
    })
    private ConceptPK conceptPK;

    //lots of other stuff
}
Теги:
spring
spring-mvc
hibernate
jpa

2 ответа

1
Лучший ответ

Всегда используйте @Override всякий раз, когда вы переопределяете метод суперкласса, если вы это сделаете, компилятор проинформирует вас о том, что вы ошиблись в реализации.

Сообщение об ошибке неверно возвращает тип данных, которые, по словам компилятора, верны, ваша sum имеет тип BigInteger not Integer.

  • Integer - это оболочка примитивного типа int. Поэтому JVM будет выполнять бокс и распаковку.
  • BigInteger является ссылочным типом, JVM не будет выполнять бокс и распаковку здесь.

Решение:

@Override
public int hashCode() {
    int hash = 3;       
    hash = 53 * hash
            + ((effectiveTime == null) ? 0 : effectiveTime.hashCode());
    hash = 53 * hash + ((id == null) ? 0 : id.hashCode());
    return hash;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    final ConceptPK other = (ConceptPK) obj;
    if (effectiveTime == null) {
        if (other.effectiveTime != null)
            return false;
    } else if (!effectiveTime.equals(other.effectiveTime))
        return false;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}
  • 0
    Я назначил награду за другой спящий вопрос. Вы готовы помочь мне с этим? вот ссылка: stackoverflow.com/questions/25454703/…
3

Помните, что хеш-коды не обязательно должны быть уникальными, они просто должны быть одинаковыми для 2-х классов, содержащих одни и те же значения полей.

Так почему бы просто не добавить хэш-код каждого поля?:

public int hashCode() {
    return id.hashCode() + effectiveTime.hashCode();
}

Конечно, это не справляется с нулевыми полями, но я оставлю это до вас. :-)

  • 0
    +1 и спасибо, что нашли время посмотреть на мою проблему.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню