[JPA] Entity Mapping : ๊ธฐ๋ณธ ํค(PK) ๋งคํ
by rlaehddnd0422๊ธฐ๋ณธ ํค(Primary Key)๋?
๊ธฐ๋ณธ ํค(Primary Key)๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ ์ด๋ธ์ ๊ฐ ํ์ ๊ณ ์ ํ๊ฒ ์๋ณํ๋ ์ด(๋๋ ์ด์ ์งํฉ)์ ๋๋ค.
์ฆ, ๊ธฐ๋ณธ ํค๋ ์ค๋ณต๋ ๋ฐ์ดํฐ๋ฅผ ํ์ฉํ์ง ์๊ณ , ๊ฐ ํ์ ์ ์ผํ๊ฒ ์๋ณํ ์ ์๋ ๊ฐ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
๊ธฐ๋ณธ ํค๋ ํ ์ด๋ธ์ ๋ชจ๋ ๋ ์ฝ๋์ ๋ํด ๊ณ ์ ํ ๊ฐ์ ๊ฐ์ ธ์ผ ํ๋ฉฐ, NULL ๊ฐ์ ๊ฐ์ง ์ ์์ต๋๋ค. - ๋ฌด๊ฒฐ์ฑ ์ ์ฝ ์กฐ๊ฑด ์ค ๊ธฐ๋ณธ ํค ์ ์ฝ์กฐ๊ฑด.
๊ธฐ๋ณธ ํค ๋งคํ
JPA๋ฅผ ์ฌ์ฉํ ๊ธฐ๋ณธ ํค ๋งคํ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ ํค๋ฅผ ๋งคํํ๊ธฐ ์ํด์๋ ๊ธฐ๋ณธ ํค๋ฅผ ์ค์ ํ ํด๋์ค(Entity)์ ํ๋์ @Id ์ด๋ ธํ ์ด์ ๋ถํ์ฃผ๋ฉด ๋ฉ๋๋ค.
๊ธฐ๋ณธ ํค๋ฅผ ํ ๋นํ๋ ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ์์ด ์์ต๋๋ค.
1. ์ง์ ํ ๋นํ๊ธฐ
: ๊ธฐ๋ณธ ํค๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ง์ ํ ๋นํด์ฃผ๋ ๋ฐฉ์์ ๋๋ค.
์๋ณ์ ๊ฐ ์์ด persistํ๊ฒ ๋๋ฉด ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
2. ์๋ ํ ๋นํ๊ธฐ
: ๋๋ฆฌ ํค ์ฌ์ฉ ๋ฐฉ์์ด๋ผ๊ณ ๋ ๋ถ๋ฆฌ๋ฉฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ์์ฑํด์ฃผ๋ ๊ฐ์ ์ฌ์ฉํฉ๋๋ค.
์๋ ํ ๋น ๋ฐฉ์, ๋๋ฆฌ ํค ์ฌ์ฉ๋ฐฉ์ ๋ํ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
2-1. IDENTITY : ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ธฐ๋ณธ ํค ๊ฐ์ ์์ฑํด์ ์๋์ผ๋ก ํ ๋นํ๋ ๋ฐฉ์
2-2. SEQUENCE : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ฅผ ์ฌ์ฉํด์ ๊ธฐ๋ณธ ํค ๊ฐ์ ์๋์ผ๋ก ํ ๋นํ๋ ๋ฐฉ์
2-3. TABLE : ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํค ์์ฑ ํ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ๊ธฐ๋ณธ ํค ๊ฐ์ ์๋์ผ๋ก ํ ๋นํ๋ ๋ฐฉ์.
ํ๋์ฉ ์์ธํ ์์๋ณด๊ฒ ์ต๋๋ค.
IDENTITY ์ ๋ต
๊ธฐ๋ณธ ํค ๊ฐ ์์ฑ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์์ํ๋ ๋ฐฉ์์ ๋๋ค. ์ฃผ๋ก MySQL, PostgreSQL, SQL Server, DB2์์ ์ฌ์ฉํฉ๋๋ค.
IDENTITY ์ ๋ต์ ์ฌ์ฉํ๋ ค๋ฉด
1. ํ ์ด๋ธ ์์ฑ ์์ AUTO_INCREMENT ์ต์ ์ ์ถ๊ฐํด์ค์ผ ํฉ๋๋ค.
create table Member (
id int not null AUTO_INCREMENT PRIMARY KEY,
name varchar(255)
);
2. ์ํฐํฐ์๋ PK์ ๋งคํ๋๋ ํ๋์ @GeneratedValue์ strategy ์์ฑ ๊ฐ์ GenerationType.IDENTITY๋ก ์ง์ ํด์ฃผ์ด์ผ ํฉ๋๋ค.
@Entity
public class Member(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
IDENTITY ์ ๋ต์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ insertํจ๊ณผ ๋์์ ๊ธฐ๋ณธํค ๊ฐ์ด ์ํฐํฐ์ ๋งคํ๋๊ธฐ ๋๋ฌธ์ insert ํ ์ดํ ๊ธฐ๋ณธ ํค ๊ฐ์ ์กฐํํ ์ ์์ต๋๋ค.
IDENTITY ์ ๋ต์์๋ ์์ธ์ ์ผ๋ก ํธ๋์ญ์ ์ ์ปค๋ฐํ์ง ์์๋ em.persist(entity)๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด insert SQL์ด ์ฆ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ฌ๋ฉ๋๋ค. (๊ธฐ๋ณธ ํค ๊ฐ์ insert ํ๋ฉด์ ๋์์ ์์ฑ)
์ฆ, IDENTITY ์ ๋ต์์๋ ์์์ฑ ์ปจํ ์คํธ์ ์ฐ๊ธฐ์ง์ฐ ๊ธฐ๋ฅ์ด ๋์ํ์ง ์์ต๋๋ค.
IDENTITY ์ ๋ต์ ์ฌ์ฉํ์ ๋ ๋งคํ๋๋ ๊ธฐ๋ณธํค ๊ฐ์ ๊ธฐ๋ณธ์ ์ผ๋ก insertํ ๋๋ง๋ค๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์กฐํํด์ ๋ค์ ๊ธฐ๋ณธ ํค ๊ฐ์ ํ์ ํ์ง๋ง, JDBC3์ ์ถ๊ฐ๋ Statement.getGeneratedKeys()๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ๋ฅผ ์ต์ด๋ก ์ ์ฅํ ๋ ์์ฑ๋ ๊ธฐ๋ณธ ํค ๊ฐ์ ์ป์ด ์ด์ผ๋ก์จ insert ํ ๋๋ง๋ค ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฐ๊ฒฐํ์ง ์๊ณ ์ต์ด ๊ธฐ๋ณธ ํค ๊ฐ์ ์์ฑํ ์ ์์ต๋๋ค.
SEQUENCE ์ ๋ต
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ ์ ์ผํ ๊ฐ์ ์์๋๋ก ์์ฑํ๋ ํน๋ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๋ธ์ ํธ์ ๋๋ค.
SEQUENCE ์ ๋ต์ ์ด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๋ธ์ ํธ๋ฅผ ์ฌ์ฉํด์ ๊ธฐ๋ณธ ํค๋ฅผ ์์ฑํฉ๋๋ค.
- ์ฌ์ฉ ๊ฐ๋ฅ DB : Oracle, PostgreSQL, DB2, H2
SEQUENCE ์ ๋ต ์ฌ์ฉ ๋ฐฉ๋ฒ
1. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ์ค๋ฅผ ์์ฑํฉ๋๋ค.
BOARD_SEQ ๋ผ๋ ์ด๋ฆ์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ฅผ ์์ฑํฉ๋๋ค
ํ์ : create sequence [sequnceName] start with [initialValue] increment by [allocationSize]
create sequence BOARD_SEQ START WITH 1 INCREMENT BY 1;
2. ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ฅผ ๋งคํํฉ๋๋ค.
@Entity
@SequenceGenerator(
name = "BOARD_SEQ_GENERATOR",
sequenceName = "BOARD_SEQ",
initialValue = 1, allocationSize = 1)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
private String data;
public Board() {
}
}
- ์ฌ๊ธฐ์ name์ Sequence ๊ฐ ์๋ Sequence Generator์ ์ด๋ฆ์ ๋๋ค.
- initialValue : DDL ์์ฑ ์์๋ง ์ฌ์ฉ๋๋ฉฐ, ์ํ์ค DDL์ ์์ฑํ ๋ ์ฒ์ ์์ํ๋ ์
- allocationSize : ์ํ์ค ํ๋ฒ ํธ์ถ์ ์ฆ๊ฐํ๋ ์๋ก ์ฑ๋ฅ ์ต์ ํ์ ์ฌ์ฉ๋ฉ๋๋ค ( default : 50 )
- ์ฌ์ฉํ ๊ธฐ๋ณธ ํค์ @Id์ ๋๋ถ์ด @GeneratedValue์ strategy ์์ฑ์ GenerationType.SEQUENCE๋ก ์ง์ ํด์ฃผ๊ณ , generator ์์ฑ์ ์ฌ์ฉํ Sequence Generator์ ์ด๋ฆ์ ๋ฐ๋์ ๋งคํํด ์ฃผ์ด์ผํฉ๋๋ค.
TestCode
public class Page_136 {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Board board = new Board();
board.setData("testData");
em.persist(board);
tx.commit();
System.out.println("board.getId() = " + board.getId());
em.close();
emf.close();
}
}
์ฐธ๊ณ : Domain์ setter, getter๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ์ํํฉ๋๋ค. ์ค์ ๊ฐ๋ฐ์์๋ ๋๋ฉ์ธ, ์ํฐํฐ์ getter, setter๋ฅผ ์ฌ์ฉํ์ง ์๋๋ก ํฉ์๋ค.
SEQUENCE ์ ๋ต ์ต์ ํ
SEQUENCE ์ ๋ต์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ฅผ ํตํด ์๋ณ์๋ฅผ ์กฐํํ๋ ์ถ๊ฐ ์์ ์ด ํ์ํฉ๋๋ค.
1. select BOARD_SEQ.NEXTVAL FROM DUAL
: ๋ค์ ์๋ณ์(๊ธฐ๋ณธํค ๊ฐ)์ ๊ตฌํ๊ธฐ ์ํด ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค ์กฐํ
2. insert into board ...
: ์กฐํํ ์ํ์ค๋ฅผ ๊ธฐ๋ณธ ํค ๊ฐ์ผ๋ก ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
insert ํ ๋ ๋ง๋ค ์ด๋ ๊ฒ ์ถ๊ฐ ์์ ์ด ์ด๋ฃจ์ด์ง๋ฉด ์ฑ๋ฅ ๋ฉด์์ ์ข์ง ์๊ฒ ์ฃ ?
JPA๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค์ ์ง์ ์ ๊ทผํ๋ ํ์๋ฅผ ์ค์ด๊ธฐ ์ํด @SequenceGenerator.allocationSize๋ฅผ ์ฌ์ฉํฉ๋๋ค.
AllocationSize๋ฅผ ์ ์ ํ ์ค์ ํ์ฌ ์ฑ๋ฅ์ ์ต์ ํํ ์ ์์ต๋๋ค.
์ํ์ค๋ฅผ ํ๋ฒ ๋ถ๋ฌ์ฌ ๋ ํ ๋น ๋ฒ์๋งํผ ๋ฉ๋ชจ๋ฆฌ์ ์ํ์ค ๊ฐ์ ํ ๋นํ์ฌ, DB ์ํ์ค์ ์ง์ ์ ์ผ๋ก ์ ๊ทผํ์ง ์๊ณ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ์ฌ ๋ค์ ์๋ณ์ ๊ฐ์ ๋ฐ์์ฌ ์ ์์ต๋๋ค.
ํ ๋น ๋ฒ์๋ฅผ ํฌ๊ฒ ์ค์ ํ๋ฉด ์ํ์ค ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋น๋๋ฅผ ์ค์ผ ์ ์์ง๋ง, ์ํ์ค ๊ฐ์ ๋ญ๋น๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
ํ ๋น ๋ฒ์๋ฅผ ์๊ฒ ์ค์ ํ๋ฉด ์ํ์ค ๊ฐ์ ๋ญ๋น๋ฅผ ์ค์ผ ์ ์์ง๋ง ์ํ์ค ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋น๋๊ฐ ์ฆ๊ฐํ์ฌ ์ฑ๋ฅ์ด ์ ํ๋ ์ ์์ต๋๋ค.
TABLE ์ ๋ต
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๊ณผ ์ ์ฌํฉ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํ์ค ์ค๋ธ์ ํธ์ฒ๋ผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ์ ์ด๋ฆ๊ณผ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ปฌ๋ผ์ ๋ง๋ค์ด ์ํ์ค๋ฅผ ํ๋ด๋ด๋ ์ ๋ต์ ๋๋ค.
์ฌ์ฉ ๋ฐฉ๋ฒ
1. ๋ฐ์ดํฐ๋ฒ ์ด์ค์ TABLE ์ ๋ต์ผ๋ก ์ฌ์ฉํ ํ ์ด๋ธ์ ์์ฑํฉ๋๋ค.
2. TABLE ์ ๋ต์ผ๋ก ์ฌ์ฉํ ํ ์ด๋ธ์ ์ํฐํฐ์ ๋งคํํด์ค๋๋ค.
@Entity
@TableGenerator(
name = "BOARD_SEQ_GENERATOR",
table = "my_sequence",
pkColumnName = "BOARD_SEQ", allocationSize = 1)
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.TABLE,
generator = "BOARD_SEQ_GENERATOR")
private Long id;
private String data;
public Board() {
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public Long getId() {
return id;
}
}
- name์ ์ํ์ค ์ ๋ต๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก table_generator์ ์ด๋ฆ์ ๋๋ค.
- table์ 1์์ ์์ฑํ ํ ์ด๋ธ์ ๋งคํํด์ค๋๋ค.
- pkColumnName์ ์ํ์ค ์ปฌ๋ผ๋ช ์ผ๋ก "sequence_name"์ด default๊ฐ์ผ๋ก ์ค์ ๋์ด ์์ต๋๋ค.
- 1์์ ํ ์ด๋ธ์ ์์ฑํ ๋ sequence_name์ผ๋ก ์ง์ ํ๋ ์ปฌ๋ผ์ด BOARD_SEQ์ผ๋ก ๋ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
๋ง์ฐฌ๊ฐ์ง๋ก ํ ์คํธ ์ฝ๋๋ฅผ ์คํํด๋ณด๋ฉด
๊ธฐ๋ณธ ํค ๊ฐ์ด ์ฆ๊ฐ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
AUTO ์ ๋ต
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ข ๋ฅ์ ๋ฐ๋ผ IDENTITY ์ ๋ต, SEQUENCE ์ ๋ต, TABLE ์ ๋ต ์ค ์๋์ผ๋ก ์ ํํด์ ๊ธฐ๋ณธ ํค๋ฅผ ์ ํํ๋ ์ ๋ต์ ๋๋ค.
์ฌ์ฉ ๋ฐฉ๋ฒ
@GeneratedType(strategy = GenerationType.Auto)๋ก ์ค์
Auto ์ ๋ต์ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ํ์ค๋ ํ ์ด๋ธ ์ ๋ต์ด ์ ํ๋ ์๋ ์์ผ๋ฏ๋ก ์ํ์ค๋ ํค ์์ฑ์ฉ ํ ์ด๋ธ์ ๋ฏธ๋ฆฌ ๋ง๋ค์ด ๋์ด์ผ ํฉ๋๋ค.
์ด ๊ท์ฐฎ์ ์ผ์ ํ์ด๋ฒ๋ค์ดํธ๊ฐ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํด์ ์ ์ ํ ์ํ์ค๋ ํค ์์ฑ์ฉ ํ ์ด๋ธ์ ๋ง๋ค์ด์ค๋๋ค.
ํค ์์ฑ ์ ๋ต์ด ํ์ ๋์ง ์์ ๊ฐ๋ฐ ์ด๊ธฐ ๋จ๊ณ๋ ํ๋กํ ํ์ ๊ฐ๋ฐ ์ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ!
<์ ๋ฆฌ>
- ์ง์ ํ ๋น : em.persist()๋ฅผ ํธ์ถํ๊ธฐ ์ ์ ๊ธฐ๋ณธ ํค๋ฅผ ํ ๋นํด์ฃผ๋ ๋ฐฉ์
- sequence ์ ๋ต : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค ์ค๋ธ์ ํธ์์ ์๋ณ์ ๊ฐ์ ํ๋ํ์ฌ ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅํ๋ ๋ฐฉ์
- table ์ ๋ต : ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค ์์ฑ์ฉ ํ ์ด๋ธ์์ ์๋ณ์ ๊ฐ์ ํ๋ํด ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅํ๋ ๋ฐฉ์
- identity ์ ๋ต : ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํฐํฐ๋ฅผ ์ ์ฅํด์ ์๋ณ์ ๊ฐ์ ํ๋ํ ํ ์์์ฑ ์ปจํ
์คํธ์ ์ ์ฅํ๋ ๋ฐฉ์
- ์์ธ์ ์ผ๋ก ์ ์ฅ(persist)๊ณผ ๋์์ insert SQL ์ด DB์ ์ ๋ฌ ๋๋ฏ๋ก ์ฐ๊ธฐ ์ง์ฐ ๊ธฐ๋ฅ์ด ๋์ํ์ง ์์ต๋๋ค
Tip : ๊ธฐ๋ณธ ํค๋ฅผ ์ค์ ํ ๋์๋ ๋น์ฆ๋์ค์ ์๋ฏธ๊ฐ ์๋ ์์ฐ ํค๋ฅผ ์ ํํ๊ธฐ๋ณด๋ค ๊ด๋ จ์๋ ์์์ ํค๋ฅผ ์ค์ ํ๋๋ก ํฉ์๋ค.
why ? ๋น์ฆ๋์ค์ ์๋ฏธ๊ฐ ์๋ ์์ฐ ํค๋ ์ธ์ ๋ ์ง ๋ณ๊ฒฝ๋ ์ ์๊ธฐ ๋๋ฌธ์.
<์ฐธ๊ณ ์๋ฃ>
'๐ Backend > Spring Data JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[JPA] ์ฐ๊ด๊ด๊ณ ๋งคํ - ์๋ฐฉํฅ ์ฐ๊ด๊ด๊ณ (1) | 2023.04.30 |
---|---|
[JPA] ์ฐ๊ด๊ด๊ณ ๋งคํ - ๋จ๋ฐฉํฅ ์ฐ๊ด๊ด๊ณ (0) | 2023.04.29 |
[JPA] Entity Mapping : ํ๋ โก๏ธ ์ปฌ๋ผ ๋งคํ (0) | 2023.04.28 |
[JPA] Entity Mapping : ๊ฐ์ฒด โก๏ธ ํ ์ด๋ธ ๋งคํ (0) | 2023.04.27 |
[JPA] ์์์ฑ ์ปจํ ์คํธ์ ์ํฐํฐ (0) | 2023.04.27 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422