2011-11-25 3 views
0

모델이 데이터베이스에서 두 번 지속되지 않고 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를 제외하고 해당 클래스가 다른 속성을 가질 수 있음을 보여주기 위해 두 클래스에 주석을 추가했습니다. 그러나 단순성을 위해 나는 단지 자신의 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; 
} 
관련 문제