'extra column'에 해당되는 글 1건
- 2015.12.23 :: jpa ManyToMany에 Column 추가하기
hibernate나 jpa나 구동 방식은 매우 흡사하나. jpa는 repository를 제공한다. 기본적으로 두개다 m:n의 경우 manytomany라는 어노테이션을 사용 하지만 가끔 m:n의 테이블에 추가 컬럼을 쓸경우가 생긴다.
이때는 manytomany라는 어노테이션을 사용하지 않고 oneToMany를 사용하여 m:n 테이블에 컬럼을 추가한다. 그럼 예제를 보자.
먼저 예제는 project라는 테이블과 person 테이블이 있고 이들을 project_groups라는 테이블로 OneToMany로 맵핑하는 구조이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | package com.zest.jpa.manytomanyextracolumn; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; @Entity(name="person") public class Person { private int idx; private String name; private String email; private String password; private List<Group> groups; public Person() { // TODO Auto-generated constructor stub } public Person(String name, String email, String password) { // TODO Auto-generated constructor stub this.name = name; this.email = email; this.password = password; } public Person(String name, String email, String password, List<Group> groups) { // TODO Auto-generated constructor stub this.name = name; this.email = email; this.password = password; this.groups = groups; } @Id @GeneratedValue(strategy = GenerationType.AUTO) public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @OneToMany(mappedBy = "person", cascade = CascadeType.ALL) public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } @Override public String toString() { // TODO Auto-generated method stub return "name=" + name + ", password=" + password + ", email=" + email; } } | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | package com.zest.jpa.manytomanyextracolumn; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; @Entity(name="project") public class Project { private int idx; private String name; private String description; private List<Group> groups; public Project() { // TODO Auto-generated constructor stub } public Project(String name, String description){ this.name = name; this.description = description; this.groups = new ArrayList<Group>(); } @Id @GeneratedValue(strategy = GenerationType.AUTO) public int getIdx() { return idx; } public void setIdx(int idx) { this.idx = idx; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @OneToMany(mappedBy = "project", cascade = CascadeType.ALL, fetch=FetchType.LAZY) public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } @Override public String toString() { // TODO Auto-generated method stub return "name=" + name + ", desc=" + description; } } | cs |
각 클래스는 @OnetoMany라는 어노티에션이 groups() 메소드에 묶여 있다. 그럼 이들을 묶어주는 groups 클래스를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package com.zest.jpa.manytomanyextracolumn; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; @Entity(name="project_groups") public class Group implements Serializable { private String role; private Person person; private Project project; public Group() { // TODO Auto-generated constructor stub } public Group(Person person, Project project, String role) { this.person = person; this.project = project; this.role = role; } @Column(name = "role") public String getRole() { return role; } public void setRole(String role) { this.role = role; } @Id @ManyToOne @JoinColumn(name="person_id") public Person getPerson() { return person; } public void setPerson(Person person) { this.person = person; } @Id @ManyToOne @JoinColumn(name="project_id") public Project getProject() { return project; } public void setProject(Project project) { this.project = project; } } | cs |
각 테이블과 맵핑되는 객체에 @ManyToOne이 존재하며 @JoinColumn으로 fk를 걸어주었다. 그리고 extra column으로 role이 존재 한다.
마지막 테스크 코드를 보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Test public void projectMakeEx(){ Person person = new Person("gno2222222", "gnogun@naver.com", "gno"); Project project = new Project("project122222", "description"); Group group = new Group(person, project, "owner"); project.getGroups().add(group); personRepository.save(person); projectRepository.save(project); } | cs |
각 person과 project의 repository를 사용하여 save를 하고 group은 project에 add 리스트를 해주었다. 구조가 project가 추가 되면 group도 추가 되는 구조이기때문에 위 처럼 선언한것이다. 물론 반대인 경우 person이 추가될때 그럼을 add 해도 추가 된다.
소스는 https://github.com/zest133/hibernateTest.git 에 있으며 기존 hibernate 소스는 이 예제때문에 hibernate 버전이 변경 됨에 따라 소스 부분이 변경된 곳이 있을것이다.