두 클래스 사이의 Association 유형별 매핑 방법에 대해서 살펴보고자 한다. 그리고 다양한 Collection의 매핑 방법 및 Collection의 주요속성인 inverse,cascade에 대해서 샘플코드를 중심으로 살펴본다.
테이블간 1:1 매핑이 있을 경우에 각각의 Entity 클래스를 정의하고 클래스간 관계를 OneToOne 매핑으로 처리한다.
@Entity public class Employee { @OneToOne private TravelProfile profile; } @Entity public class TravelProfile { @OneToOne private Employee employee; }
위의 예를 보면 Employee 와 TravelProfile가 각각 OneToOne이라는 Annotation을 기재하여 매핑처리한 것을 알수 있다.
테이블간 1:N 매핑이 있을 경우에 각각의 Entity 클래스를 정의하고 한쪽에는 OneToMany, 다른쪽에는 ManyToOne 이라는 Annotation을 기재하여 관계를 나타낸다.
@Entity public class Department{ @OneToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne private Department department; }
위의 예를 보면 Department:User = 1:N 의 관계가 있으며 그 관계에 대해서 Department 클래스에서 OneToMany로 표시하고 User 클래스에서 ManyToOne으로 표시하여 관계를 나타냈다.
Collection은 위의 예에서 사용된 Set 이외에도 List,Map를 사용할 수 있는데 각각의 사용법은 다음과 같다
java.util.Set 타입으로 <set>을 이용하여 정의한다. 객체의 저장 순서를 알 수 없으며, 동일 객체의 중복 저장을 허용하지 않는다. (HashSet 이용) 다음은 set 태그를 이용하여 Collection 객체를 정의한 소스 코드의 예이다
@Entity public class Department{ @OneToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); }
java.util.List 타입으로 <list>를 이용하여 정의한다. List 타입의 경우 저장된 객체의 순서를 알 수 있으며, 저장 순서를 테이블에 보관하기 위해서 별도 인덱스 컬럼 정의가 필요하다. (ArrayList 이용) 다음은 list 태그를 이용하여 Collection 객체를 정의한 소스 코드의 예이다
@Entity public class Department{ @OneToMany(targetEntity=User.class ) private List<User> users = new ArrayList(0); }
java.util.map 타입으로 <map>을 이용하여 (키,값)을 쌍으로 정의한다. (HashMap 이용) 다음은 map 태그를 이용하여 Collection 객체를 정의한 소스 코드의 예이다. Key 설정을 위해 MapKey라는 Annotation을 추가적으로 정의해야 한다.
@Entity public class Department{ @OneToMany(targetEntity=User.class) @MapKey(name="userId") private Map<String,User> users ; }
1:N(부모:자식)관계 지정에 있어서 자식쪽에서 부모에 대한 참조 관계를 가지고 있느냐 없느냐에 따라서 참조관계가 있으면 양방향 관계, 없으면 단방향 관계로 정의된다.
자식 Entity에 부모 Entity에 대한 참조정보 없이 정의한다.
@Entity public class Department{ @OneToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); } @Entity public class User{ @Column(name="DEPT_ID") private String deptId; }
위의 예에서 보면 User 클래스에서 Department 클래스에 대한 참조관계를 지정하지 않고 단순하게 테이블의 컬럼 DEPT_ID와의 매핑으로 deptId를 지정한 것을 알 수 있다.
자식 Entity에 부모 Entity에 대한 참조정보를 지정하여 정의한다.
@Entity public class Department{ @OneToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne private Department department; }
위의 예에서 보면 User 클래스에서 Department 클래스에 대한 ManyToOne Annotation을 통해 매핑관계를 지정한 것을 알 수 있다.
mappedBy와 cascade는 Collection 정의시 중요한 의미를 가지는 속성 중의 하나로, 다음과 같은 의미를 지닌다.
mappedBy와 cascade를 모두 정의하여 사용할 경우에는 자식 Entity에서 관계연결 처리를하고 부모 Entity에서 CUD처리시 자식 Entity도 자동으로 처리된다.
@Entity public class Department{ @OneToMany(targetEntity=User.class,mappedBy="deptId",cascade={CascadeType.PERSIST, CascadeType.MERGE}) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne(targetEntity=Department.class) private Department department; }
// User(자식) Entity의 setDepartment 메소드를 통해서 관계설정 user.setDepartment(department); // 부모 entity의 저장으로 자식까지 동시처리 em.persist(department);
mappedBy만 정의하여 사용할 경우에는 자식 Entity에서 관계연결 처리를하고 부모,자식 각자 CUD처리한다.
@Entity public class Department{ @OneToMany(targetEntity=User.class,mappedBy="deptId") private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne(targetEntity=Department.class) private Department department; }
// User(자식) Entity의 setDepartment 메소드를 통해서 관계설정 user.setDepartment(department); // 부모/자식 entity의 각각 처리 em.persist(department); em.persist(user);
cascade만 정의하여 사용할 경우에는 부모 Entity에서 관계연결 처리를 하고 부모 Entity에서 CUD처리시 자식 Entity도 자동으로 처리된다.
@Entity public class Department{ @OneToMany(targetEntity=User.class,cascade={CascadeType.PERSIST, CascadeType.MERGE}) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne(targetEntity=Department.class) private Department department; }
// Department(부모) Entity의 getUsers().add 메소드를 통해서 관계설정 department.getUsers().add(user); // 부모 entity의 저장으로 자식까지 동시처리 em.persist(department);
모두 정의하지 않을때는 부모 Entity에서 관계 연결 처리를 하고 부모,자식 각자 CUD처리한다.
@Entity public class Department{ @OneToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToOne(targetEntity=Department.class) private Department department; }
// Department(부모) Entity의 getUsers().add 메소드를 통해서 관계설정 department.getUsers().add(user); // 부모/자식 entity의 각각 처리 em.persist(department); em.persist(user);
테이블간 M:N 매핑이 있을 경우에 각각의 Entity 클래스를 정의하고 양쪽에 ManyToMany이라는 Annotation을 기재하여 관계를 나타낸다.
@Entity public class Role{ @ManyToMany(targetEntity=User.class) private Set<User> users = new HashSet(0); } @Entity public class User{ @ManyToMany @JoinTable(name="AUTHORITY", joinColumns=@JoinColumn(name="USER_ID"), inverseJoinColumns=@JoinColumn(name="ROLE_ID")) private Set<Role> roles = new HashSet(0); }
위의 예를 보면 Role:User = M:N 의 관계가 있으며 그 관계에 대해서 Role클래스에서 ManyToMany로 표시하고 User 클래스에서 ManyToMany로 표시하여 관계를 나타내면서 User 클래스에서 관계를 위한 별도의 테이블에 대한 정의를 하고 있다. 이 경우에 ROLE과 USER를 연결하는 관계 테이블로 AUTHORITY가 사용된 것을 알 수 있다.