簡體   English   中英

jpa / hibernate中的對稱組合鍵

[英]Symmetric composite key in jpa/hibernate

我正在嘗試確保模型不會在數據庫中保留兩次,並且其ID是對稱的。 在對稱組合id下,我的意思是:

@Entity
public class Item {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "item_id", unique = true, nullable = false)
    public Long id;

    // other properties ...
}

@Entity
public class Pair {
    @EmbeddedId
    public PairId id;   

    // other properties...

    @Embeddable
    public static class PairId implements Serializable {

        @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
        @JoinColumn(name="source_item_id")
        public Item source;

        @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH, CascadeType.DETACH})
        @JoinColumn(name="target_item_id")
        public Item target;

        @Override
        public boolean equals(Object o) {
             if(this == o){
               return true;
             }
             if (o instanceof PairId == false){
               return false;
             }

             PairId other = (PairId) o;
             return (this.source.equals(other.source) && this.target.equals(other.target)) ||
                    (this.source.equals(other.target) && this.target.equals(other.source));
    }

        @Override
        public int hashCode() { //probably not the best approach
             return source.hashCode() + target.hashCode();
        }
    }
}

例:

Item i1 = new Item();
Item i2 = new Item();
//persist items into the database ...
PairId pId1 = new PairId(i1, i2);
PairId pId2 = new PairId(i2, i1);
Pair p1 = new Pair(pId1);
//persist p1 into the database
Pair p2 = new Pair(pId2);
//calling persist should not add new entry to the database, since p2 is symmetrical to p1 and already exists in the database
Pair p3 = findById(pId2); 
//p3 should now contain p1 also

您是否知道我該如何實施這種行為? 提前致謝!

編輯:在這兩個類上添加了注釋,以表明這些類除了上面列出的ID之外,還可以具有(並且具有)其他屬性。 但是為了簡單起見,我只是將它們的ID保留為單獨的固定資產。

也許,也許您可​​以放棄Pair想法並在Item使用自我參考。 這樣,您的表就更少了,代碼更簡潔,也沒有復合鍵了。

碼:

@Entity
public class Item
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @OneToOne
    @JoinColumn(name = "source_id", referencedColumnName = "id")
    private Item source;

    @OneToOne(mappedBy = "source")
    private Item target;
}

首先,我不會使用復合ID。 使用自動生成的代理鍵,並將這兩項都存儲為常規屬性。

然后,當成對存儲項目時,我將確保始終以相同順序存儲它們。 例如,源ID應始終比目標ID小。 使用封裝可以確保這一點:

public void setItems(Item i1, Item i2) {
    if (i1.getId().compareTo(i2.getId()) < 0) {
        this.source = i1;
        this.target = i2;
    }
    else {
        this.source = i2;
        this.target = i1;
    }
}

暫無
暫無

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

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