簡體   English   中英

在休眠復合主鍵中有沒有覆蓋 equals 和 hashCode 的 find

[英]there is find without overidding equals and hashCode in hibernate composite primary key

我正在使用休眠 4.3.10。

當引用復合主鍵時,我的實體看起來像 next (從@Master Slave 得到答案后添加了 equals() 和 hashCode() )

@Entity
@Table(name="compositepk")
public class Car {
    @EmbeddedId
    private CarPK carPK;
    private String name;

    public CarPK getCarPK() {
        return carPK;
    }
    public void setCarPK(CarPK carPK) {
        this.carPK = carPK;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }

    @Embeddable
    public static class CarPK implements Serializable{

        private static final long serialVersionUID = -5202331188724915048L;
        private int chassisNumber;
        private int engineNumber;

        public int getChassisNumber() {
            return chassisNumber;
        }
        public void setChassisNumber(int chassisNumber) {
            this.chassisNumber = chassisNumber;
        }
        public int getEngineNumber() {
            return engineNumber;
        }
        public void setEngineNumber(int engineNumber) {
            this.engineNumber = engineNumber;
        }

    @Override
    public boolean equals(Object obj) {
        if(obj instanceof CarPK) {
            CarPK car = (CarPK)obj;
            if(this.getChassisNumber().intValue() == car.getChassisNumber().intValue() &&
                    this.getEngineNumber().intValue() == car.getEngineNumber().intValue()) {
                return true;
            } else {
                return false;
            }
        }

        return false;
    }

    @Override
    public int hashCode() {
        return this.chassisNumber.hashCode()+this.engineNumber.hashCode();
    }
    } 

}

hibernate 文檔說我們必須在復合主鍵中實現 equals() 和 hashCode() 。

但是,我發現在 CarPK 中不覆蓋它們就沒有任何問題。 我可以比較汽車並將它們添加到 Set 並得到正確的結果。 例如,以下是比較代碼:

Car.CarPK pk = new Car.CarPK();
pk.setChassisNumber(3);
pk.setEngineNumber(2017);

Car c1 = (Car) session1.get(Car.class, pk);
Car c2 = (Car) session2.get(Car.class, pk);

if(c1.equals(c2)) {
    System.out.println("==");
} else {
    System.out.println("!=");
}

如果chassisNumber 和engineNumber 相同,則此代碼打印“!=”並打印“==”。

(修改上面的代碼后,在不同的會話中得到相同的結果,上面的代碼打印“!=”,為什么?不應該打印“==”,因為我已經實現了equals()和hashCode()? )

那么當我沒有在 CarPK 中實現 equals() 和 hashCode() 時,任何人都可以告訴我問題嗎?

提前致謝!

我花了一些時間才弄清楚,但您還必須覆蓋Car equalshashCode

@Override
public boolean equals(Object obj) {
    if(obj instanceof Car) {
        Car that = (Car) obj;
        return this.carPK.equals(that.carPK);
    }

    return false;
}

@Override
public int hashCode() {
    return this.carPK.hashCode();
}

順便說一句,您的hashCodeCarPK的實現是危險的(並且是錯誤的,因為它無法編譯)。 生成 2 CarPK具有相同hashCode但不equals CarPK太容易了

Car.CarPK pk1 = new Car.CarPK();
pk1.setChassisNumber(3);
pk1.setEngineNumber(2017);
Car.CarPK pk2 = new Car.CarPK();
pk2.setChassisNumber(1500);
pk2.setEngineNumber(520);

System.out.println(pk1.hashCode()); //prints 2020
System.out.println(pk2.hashCode()); //prints 2020

//Same hashCode, should be equal, just checking...
System.out.println(pk1.equals(pk2)); //prints false !

我推薦你這個實現,它更難產生碰撞

@Override
public int hashCode() {
    return Objects.hash(chassisNumber, engineNumber);
}

您的測試有效,因為您處於相同的會話/持久性上下文中。 假設您嘗試在兩個不同的持久上下文中加載實體(再次使用相同的值),您將意識到它是一個不同的 java 對象。

這就是為什么您必須實現業務鍵均衡,因此hashCodeequals將告訴 hibernate 如何推理對象相等,並且無論對象的狀態如何(瞬態、附加、分離)都應該保持不變。 基於上述,id 屬性不是哈希/等於合約的一部分,因為它的值取決於狀態

文檔

Hibernate 使用 Hibernate 會話來管理這種唯一性。 當您使用 new() 創建一個對象,然后將其保存到會話中時,Hibernate 現在知道每當您查詢一個對象並找到該特定對象時,Hibernate 都應該返回該對象的實例。 而 Hibernate 會做到這一點。 但是,一旦您關閉 Hibernate 會話,所有賭注都將取消。 如果你一直持有一個在你現在關閉的 Hibernate 會話中創建或加載的對象,Hibernate 無法知道這些對象。 因此,如果您打開另一個會話並查詢“相同”對象,Hibernate 將返回一個新實例。 因此,如果您在會話之間保留對象集合,您將開始遇到奇怪的行為(主要是集合中的重復對象)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM