Team, Player (1:다) 매핑을 설정하여 Player 객체를 구하면 Player가 소속된 Team정보를 함께 구할 수 있고, Team객체를 구하면 팀에 소속된 Player의 정보를 확인할 수 있게 된다.
양방향 관계 설정 절차
Player는 Team의 PK를 FK로 포함하게 되므로 관계를 소유한 측이 되며, Team은 그 반대편이므로 Team 클래스 내의 List<Player>속성에 @OneToMany(mappedBy="team") 을 설정해준다.
1. @Entity : 양쪽 클래스 모두에게 설정
2. @ManyToOne : Player 클래스의 Team속성에 설정
3. @OneToMany(mappedBy="team") : Team 클래스의 List<Player>속성에 설정, 여기서 team은 Player의 Team속성
Player 클래스에는 Team형 속성이, Team 클래스에슨 List<Player>형 속성이 있어야 한다.
4. 위와같이 형식적인 설정을 마치면, 내용면에서도 Player에는 Team속성을, Team에는 List<Player>속성을 초기화하여 저장하면 이후에 Team에서는 Player정보를, Player에서는 Team정보를 함께 확인할 수 있는 양방향 관계가 구현된다.
src/META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="players">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>jpatest.Player</class>
<class>jpatest.Team</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver" />
<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:oracle" />
<!-- I work in this example without user / password.-->
<property name="javax.persistence.jdbc.user" value="scott" />
<property name="javax.persistence.jdbc.password" value="tiger" />
<!-- EclipseLink should create the database schema automatically -->
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
</persistence>
jpatest.Player
package jpatest;
import java.util.*;
import java.io.Serializable;
import javax.persistence.*;
@Entity
public class Player implements Serializable{
@Id
@GeneratedValue
private int id;
private String name;
private String phone;
@ManyToOne(optional=true)
private Team team;
public Player() {}
public Player(String name, String phone) {
this.name = name;
this.phone = phone;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Team getTeam() {
return team;
}
public void setTeam(Team team) {
this.team = team;
}
}
jpatest.Team
package jpatest;
import java.io.Serializable;
import java.util.*;
import javax.persistence.*;
@Entity
public class Team implements Serializable {
@Id
@GeneratedValue
private int id;
String name;
String loc;
@OneToMany(mappedBy="team") // 관계를 소유한 측 Player 클래스의 Team team 변수이름을 가리킴
List<Player> players;
public Team() {}
public Team(String name, String loc) {
this.name = name;
this.loc = loc;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
public List<Player> getPlayers() {
return players;
}
public void setPlayers(List<Player> players) {
this.players = players;
}
}
jpatest.JPATetst
package jpatest;
import java.util.*;
import javax.persistence.*;
/* 2개의 Entity 클래스 간에 양방향 관계 매핑의 예 */
/* Foreign Key를 포함하고 있는 테이블이 관계를 소유한 측이며,
* 그 반대편의 빈 클래스에 mappedBy 속성을 설정해 준다.
* Team, Player를 저장할 때 Team에서는 Player들을, Player에는 Team을 설정해주면
* 양방향 관계를 설정하여 저장할 수 있고 이후에 Player객체를 구하면 해당 Player가 소속된 Team정보
* 도 함께 확인할 수 있고, Team객체를 구하면 그 팀에 소속된 모든 Player들의
* 정보도 함께 확인할 수 있다.
*/
public class JPATest {
private static final String PERSISTENCE_UNIT_NAME = "players";
private static EntityManagerFactory factory;
static {
factory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);
}
public static void main(String[] args)throws Exception{
insert();
select();
printTeam();
}
public static void insert() throws Exception {
List<Player>list = createPlayer();
Team[] team = createTeam();
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();
/* 아래의 라인을 사용하지 않으면 Player 에서 Team으로 단방향 관계만 설정됨 */
team[0].setPlayers(list); // 한팀에 모든 선수를 설정한다.
for(int i=0;i<team.length;i++){
em.persist(team[i]); // 팀 정보를 데이터베이스에 저장
}
for(int i=0;i<list.size();i++){
Player p = list.get(i);
p.setTeam(team[0]); // Player에게 Team을 설정한다
em.persist(p); // 테이블에 레코드 한개 저장
}
em.getTransaction().commit();
em.close();
}
public static void select() throws Exception {
EntityManager em = factory.createEntityManager();
Query query = em.createQuery("SELECT p FROM Player p");
List<Player> list = query.getResultList();
for(int i=0;i<list.size();i++){
Player p = list.get(i);
int id = p.getId();
String name = p.getName();
Team team = p.getTeam();
System.out.println("id:"+id+"\tName:"+name+"\tTeam:"+team.getName());
}
em.close();
}
public static void update(int id) throws Exception {
EntityManager em = factory.createEntityManager();
Player p = em.find(Player.class, id);
em.getTransaction().begin();
p.setPhone("3333-4444-5555");
em.persist(p);
em.getTransaction().commit();
em.close();
}
public static void delete(int id) throws Exception {
EntityManager em = factory.createEntityManager();
Player p = em.find(Player.class, id);
em.getTransaction().begin();
em.remove(p); // 테이블에서 레코드 삭제
em.getTransaction().commit();
em.close();
}
/* 아이디를 파라미터로 받아서 테이블에서 검색하여 Player객체를 리턴하는 메소드 */
public static Player findById(int id){
EntityManager em = factory.createEntityManager();
Player p = em.find(Player.class, id);
em.close();
return p;
}
/* 양방향 관계를 설정했기 때문에 Team에서 Player정보를 포함하고 있다.*/
public static void printTeam(){
EntityManager em = factory.createEntityManager();
Query query = em.createQuery("select t from Team t order by t.id");
List<Team> list = query.getResultList();
for(int i=0;i<list.size();i++){
Team t = list.get(i);
String name = t.getName();
System.out.println("팀명:"+name);
List<Player> pList = t.getPlayers();
for(int k=0;k<pList.size();k++){
Player p = pList.get(k);
System.out.print(p.getName()+" ");
}
System.out.println();
}
em.close();
}
private static List<Player> createPlayer(){
ArrayList<Player> list = new ArrayList<Player>();
list.add(new Player("박세리","2345-7564-6578"));
list.add(new Player("박찬호", "643-745-346"));
list.add(new Player("박지성", "0987-789-5432"));
list.add(new Player("김연아", "456-345-876"));
list.add(new Player("차범근", "534-8756-7890"));
return list;
}
private static Team[] createTeam(){
Team[] t = {
new Team("Team A", "서울시"),
new Team("Team B", "경기도")
};
return t;
}
}