2011-11-25 51 views
0

我在試圖確保模型不會在數據庫中持續兩次,並且其ID是對稱的。在對稱的複合ID我指的是以下幾點:jpa/hibernate中的對稱組合鍵

@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作爲獨立的財產。

回答

0

首先,我不會使用複合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; 
    } 
} 
0

也許,只是也許你可以放下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; 
}