오늘 공부의 목표란다!
연관관계가 필요한 이유
=> 객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다.
예제 시나리오
- 회원과 팀이 있다
- 회원은 하나의 팀에만 소속될 수 있다.
- 회원과 팀은 다대일 관계다.
//==============Member.class
package jpabook.jpashop.domain;
import javax.persistence.*;
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME" , nullable = false)
private String username;
@Column(name = "TEAM_ID")
private long teamId;
}
//==============Team.class
package jpabook.jpashop.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
}
//============JpaMain.class
package jpabook.jpashop;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
tx.commit();
}catch(Exception e){
tx.rollback();
}finally{
//code
em.close();
}
emf.close();
}
}
이렇게 파일을 세팅하고 실행해 보면...
밑에 처럼 콘솔창에 쿼리가 날아간것을 확인할 수 있다.
Hibernate:
create table Member (
MEMBER_ID bigint not null,
TEAM_ID bigint,
USERNAME varchar(255) not null,
primary key (MEMBER_ID)
)
Hibernate:
create table Team (
TEAM_ID bigint not null,
name varchar(255),
primary key (TEAM_ID)
)
위처럼 한 것이 테이블에 딱 맞춰서 한 설계이다
근데 이렇게하면 생기는 문제점이 있다!
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUsername("member1");
member.setTeamId(team.getId());
em.persist(member);
Member findMember = em.find(Member.class, member.getId());
Long findTeamId = findMember.getTeamId();
Team findTeam = em.find(Team.class, findTeamId);
평소에 Member 테이블과 Team 테이블이 서로 연관관계에 있으면
select * from member m
join team t on m.team_id = t.team_id;
그냥 이렇게 ANSI조인으로 꺼내면 간단한데 위에서는 member 세팅 해주고 team id 찾아서
또 그걸로 team name을 찾아야 한다 => 뭔가 엄청 번거로워 ㅠㅠ
그럼 객체지향 스럽게 테이블을 짠다면?
그리고 Member.class 에 teamId를 사용하지 않고 그냥 Team class를 변수로 선언해버린다.
package jpabook.jpashop.domain;
import javax.persistence.*;
@Entity
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
/* @Column(name = "TEAM_ID")
private long teamId;*/
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 뭘 조인해야 하는지도 알려줌!
private Team team;
}
그냥 team을 변수로 선언하면 굳이 여러번 왓다갓다 할 필요가 없다!
근데 그러면 DB에 둘의 관계를 알려줘야함.
일대다인지, 다대일인지, 다대다인지 말이다!
그래서 Team 위에 ManyToOne이라고 붙여야 한다.
그리고 조인할 컬럼이 무엇인지 알려줘야 한다.
최종적으로는 다음과 같이 그림을 그릴 수 있다.
그럼 이제 이렇게 사용할 수 있다.
package jpabook.jpashop;
import jpabook.jpashop.domain.Member;
import jpabook.jpashop.domain.Team;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUsername("member1");
member.setTeam(team); // 알아서 PK값 꺼내서 FK값으로 넣어줌
em.persist(member);
em.flush();
em.clear();
Member findMember = em.find(Member.class, member.getId());
Team findTeam = findMember.getTeam();
System.out.println("findTema : " + findTeam.getName());
tx.commit();
}catch(Exception e){
tx.rollback();
}finally{
//code
em.close();
}
emf.close();
}
}
콘솔창 보면 결과를 확인할 수 있다.
Hibernate:
create table Member (
MEMBER_ID bigint not null,
USERNAME varchar(255),
TEAM_ID bigint,
primary key (MEMBER_ID)
)
Hibernate:
create table Team (
TEAM_ID bigint not null,
name varchar(255),
primary key (TEAM_ID)
)
Hibernate:
alter table Member
add constraint FKl7wsny760hjy6x19kqnduasbm
foreign key (TEAM_ID)
references Team
7월 15, 2021 9:38:37 오후 org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@2a492f2a'
Hibernate:
call next value for hibernate_sequence
Hibernate:
call next value for hibernate_sequence
Hibernate:
/* insert jpabook.jpashop.domain.Team
*/ insert
into
Team
(name, TEAM_ID)
values
(?, ?)
Hibernate:
/* insert jpabook.jpashop.domain.Member
*/ insert
into
Member
(TEAM_ID, USERNAME, MEMBER_ID)
values
(?, ?, ?)
Hibernate:
select
member0_.MEMBER_ID as MEMBER_I1_0_0_,
member0_.TEAM_ID as TEAM_ID3_0_0_,
member0_.USERNAME as USERNAME2_0_0_,
team1_.TEAM_ID as TEAM_ID1_1_1_,
team1_.name as name2_1_1_
from
Member member0_
left outer join
Team team1_
on member0_.TEAM_ID=team1_.TEAM_ID
where
member0_.MEMBER_ID=?
findTema : TeamA
'Spring' 카테고리의 다른 글
7. 스프링 / 2021-07-18 (연관관계 매핑 ) (0) | 2021.07.18 |
---|---|
6. 스프링 공부 / 양방향 연관관계와 연관관계의 주인 (0) | 2021.07.15 |
4. 스프링 공부 / 2021-07-14 (실전1 - 요구사항 분석과 기본 매) (0) | 2021.07.14 |
3. 스프링 공부 / 2021-07-14 (필드와 컬럼 매핑 ~) (0) | 2021.07.14 |
2. 스프링JPA 공부 / 2021-07-13 (준영속 상태) (0) | 2021.07.13 |