【问题标题】:BigInteger hashcode for embeddable composite key可嵌入复合键的 BigInteger 哈希码
【发布时间】:2014-06-18 14:02:40
【问题描述】:

我在数据库中有一个两列主键,我需要使用 hibernate 4.2 和 jpa 使用 spring mvc 应用程序对其进行建模。从我在网上阅读的内容看来,我的复合键类ConceptPK 必须包含一个哈希码方法。问题是主键的两个元素之一是 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
}

【问题讨论】:

    标签: java spring hibernate spring-mvc jpa


    【解决方案1】:

    当你重写 super 的方法时,总是使用@Override 类,如果你这样做了,编译器会在你做错的时候通知你 实施。

    编译器所说的错误消息错误的返回数据类型是正确的,你的sum的类型是BigInteger而不是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;
    }
    

    【讨论】:

    【解决方案2】:

    请记住,哈希码不需要是唯一的,它们只需要对于包含相同字段值的 2 个类相同即可。

    那么为什么不把每个字段的 hashCode 加起来呢?:

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

    当然,这不能处理空字段,但我会留给你。 :-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 2011-02-25
      • 1970-01-01
      • 2018-04-07
      相关资源
      最近更新 更多