2013-02-28 5 views
2

다음과 같은 문제가 발생합니다. 내 Employee 클래스를 다음 데이터베이스 스키마 ()에 매핑해야합니다. 여기서 id1과 id2는 복합 기본 키) :외래 키가 기본 키의 일부인 경우 복합 키로 자체 조인을 매핑하는 방법

-------------------------- 
| id1 | id2 | ManagerId2 | 
-------------------------- 
| 1 | 1 | NULL  | <--- Have no manager/Can be manager of many 
-------------------------- 
| 1 | 2 | 1   | <--- Is manager/Has manager 1-1 
-------------------------- 
| 1 | 3 | 1   | <--- Is manager/Has manager 1-1 
-------------------------- 

내가 외래 키가 기본 키 그것을 참조와 같은 열 (열 수가 같아야 것을 알고 있습니다). 요점은 Employeeid1 = 1을 삽입하면 id1 = 1 인 관리자 만 참조해야한다는 것입니다. 있는 방법 무결성을 유지하고 다음과 같은 시나리오를 피하기 위해 :

--------------------------------------- 
| id1 | id2 | ManagerId1 | ManagerId2 | 
--------------------------------------- 
| 1 | 1 | NULL  | NULL  | <--- Have no manager/Can be manager of many 
--------------------------------------- 
| 2 | 1 | NULL  | NULL  | <--- Have no manager/Can be manager of many 
--------------------------------------- 
| 1 | 2 | 2   | 1   | <--- THIS IS NOT ALLOWED 
--------------------------------------- 
| 1 | 3 | 2   | 1   | <--- NOR THIS 
--------------------------------------- 

지금까지 내가 (는 ManagerId2 필드를 채 웁니다하지 않습니다 간단하게 예상대로 테이블을 만들고 있지만) 다음과 같은 매핑이 가지고있는 최선 :

@Entity 
@Table(name="Employee") 
public class Employee { 

    public Employee(){ 
    } 

    @EmbeddedId 
    private EmployeeId id; 
    public void setId(EmployeeId id) { 
     this.id = id; 
    } 
    public EmployeeId getId() { 
     return id; 
    } 

    @ManyToOne(cascade={CascadeType.ALL}) 
    @JoinColumns({ 
     @JoinColumn(name = "id1", referencedColumnName = "id1", insertable=false, updatable=false), //its fine to have this attribute not insertable nor updatable 
     @JoinColumn(name = "id2_manager", referencedColumnName = "id2", insertable=false, updatable=false) //but I must be able to update this one! 
    }) 
    private Employee manager; 
    public Employee getManager() { 
     return manager; 
    } 
     public void setManager(Employee manager) { 
     this.manager = manager; 
    } 
} 

@Embeddable 
public class EmployeeId implements Serializable{ 

    public EmployeeId() { 

    } 

    public EmployeeId(int id1, int id2) { 
     this.id1 = id1; 
     this.id2 = id2; 
    } 

    private int id1; 

    private int id2; 

    public int getId1() { 
     return id; 
    } 

    public void setId(int id1) { 
     this.id1 = id1; 
    } 

    public int getId2() { 
     return id2; 
    } 

    public void setId2(int id2) { 
     this.id2 = id2; 
    } 

      //hashCode and equals properly overriden 
} 

하루 종일 고글 거리는 후 나는 아무것도 찾을 수 없다고 생각합니다! 누군가 내가 잘못하고있는 것을 나에게 친절하게 보여줄 수 있습니까? 아니면 좋은 자료를 가르쳐 줄 수 있습니까?

추신 : 제가 DB 스키마를 변경할 수 없습니다, 그것은 옵션

+0

이 테이블은 ManagerId1 열이 있거나하지 않는 이유는 무엇입니까? –

+0

아니요. 제 말은 스키마가 필수이고 스키마는 id1, id1 및 managerId2 만 포함되어 있기 때문에 존재하지 않아야합니다. – renatoargh

+0

왜 "ManagerId1 필드를 채우지 않습니까?" 그건 오타예요? –

답변

1

임 주석이 작업을 수행하는 방법을 잘 아니지만, 필자는 당신을 도울 수있는 해결 방법을 발견했다.

@Entity 
@Table(name = "Employee") 
public class Employee { 

    @EmbeddedId 
    private EmployeeId id; 

    private Integer id2_manager; 

    @PrePersist 
    @PreUpdate 
    public void prePersistUpdate() { 
     if (manager != null) 
      id2_manager = manager.getId().getId2(); 
    } 

    public Employee() { 
    } 

    public void setId(EmployeeId id) { 
     this.id = id; 
    } 

    public EmployeeId getId() { 
     return id; 
    } 

    @ManyToOne(cascade = { CascadeType.ALL }) 
    @JoinColumns({ @JoinColumn(name = "id1", referencedColumnName = "id1", insertable = false, updatable = false), 
      @JoinColumn(name = "id2_manager", referencedColumnName = "id2", insertable = false, updatable = false, nullable = true) }) 
    private Employee manager; 

    public Employee getManager() { 
     return manager; 
    } 

    public void setManager(Employee manager) { 
     this.manager = manager; 
    } 
} 

테스트

static EntityManagerFactory emf; 
    static EntityManager em; 

    public static void main(String[] args) { 

     emf = Persistence.createEntityManagerFactory("unit"); 
     em = emf.createEntityManager(); 

     Employee manager = new Employee(); 
     manager.setId(new EmployeeId(1, 1)); 

     Employee e1 = new Employee(); 
     e1.setId(new EmployeeId(1,2)); 
     e1.setManager(manager); 


     em.getTransaction().begin(); 

     em.persist(manager); 
     em.persist(e1); 

     em.getTransaction().commit(); 

     Employee e2 = em.find(Employee.class, new EmployeeId(1, 2)); 

     System.out.println(e2.getManager().getId().getId1() + "-" + e2.getManager().getId().getId2()); 
     // prints 1-1 

    }