'manytomany'에 해당되는 글 2건

  1. 2015.12.23 :: jpa ManyToMany에 Column 추가하기
  2. 2015.12.07 :: hibernate(9)
개발관련/Spring 2015. 12. 23. 13:29

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 버전이 변경 됨에 따라 소스 부분이 변경된 곳이 있을것이다. 


posted by 제스트
:
개발관련/Spring 2015. 12. 7. 17:57

다대다에 대해서 알아보자. 


바로 소스 공개...

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
package com.zest.hibernate.chapter8.manytomanymapping;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
 
@Entity
public class Delegate {
 
    
    private int delegateId;
    private String delegateName;
    private List<Event> events = new ArrayList<Event>();
 
    
    @Id
    @GeneratedValue
    public int getDelegateId() {
        return delegateId;
    }
 
    public void setDelegateId(int delegateId) {
        this.delegateId = delegateId;
    }
 
    public String getDelegateName() {
        return delegateName;
    }
 
    public void setDelegateName(String delegateName) {
        this.delegateName = delegateName;
    }
 
    // 결과를 담을 테이블명을 정의 .
    @ManyToMany
    @JoinTable(name = "JOIN_DELEGATE_EVENT", joinColumns = { @JoinColumn(name = "delegateId") }, inverseJoinColumns = { @JoinColumn(name = "eventId") }    )
    public List<Event> getEvents() {
        return events;
    }
 
    public void setEvents(List<Event> events) {
        this.events = events;
    }
 
}
 
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
 
package com.zest.hibernate.chapter8.manytomanymapping;
 
import java.util.ArrayList;
import java.util.List;
 
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
 
@Entity
public class Event {
 
    
    private int eventId;
    private String eventName;
    private List<Delegate> delegates = new ArrayList<Delegate>();
 
    @Id
    @GeneratedValue
    public int getEventId() {
        return eventId;
    }
 
    public void setEventId(int eventId) {
        this.eventId = eventId;
    }
 
    public String getEventName() {
        return eventName;
    }
 
    public void setEventName(String eventName) {
        this.eventName = eventName;
    }
 
    @ManyToMany
    @JoinTable(name = "JOIN_DELEGATE_EVENT", joinColumns = { @JoinColumn(name = "eventId") }, inverseJoinColumns = { @JoinColumn(name = "delegateId") })
    public List<Delegate> getDelegates() {
        return delegates;
    }
 
    public void setDelegates(List<Delegate> delegates) {
        this.delegates = delegates;
    }
 
}
 
cs


두개의 객체를 선언하였다. 여기도 마찬가지로 새로운 어노테이션이 등장한다. 

@ManyToMany 이다. 그리고 JoinColumn이 아닌 JoinTable이다. 

@ManyToMany는 두개의 객체 두군데 다 선언을 한다. 그리고 필연적으로 @JoinTable을 사용해야한다. 각 속성을 알아보자. name은 m:n에 대한 데이터를 저장하는 테이블 이며, jonColumns와 inverseJoinColumkns가 존재한다. joinColumns는 join이 되는 컬럼 여기선 상호간의 컬럼 아이디를 써준다. 



결과 쿼리를 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Delegate (delegateName, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.Event (eventName, eventId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
Hibernate: insert into TESTSCHEMA.JOIN_DELEGATE_EVENT (eventId, delegateId) values (?, ?)
cs


JOIN_DELEGATE_EVENT 테이블 생성되며 각 각의 정보가 m:n으로 맵핑이 된다.


하이버네이트 모든 코드는 https://github.com/zest133/hibernateTest.git 여기에 저장되어 있다.

posted by 제스트
: