์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ ๊ธฐ์ดˆ


๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฐจ์ด๋ฅผ ์ดํ•ดํ•œ๋‹ค. ๊ฐ์ฒด์˜ ์ฐธ์กฐ์™€ ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ดํ•ดํ•œ๋‹ค.

์šฉ์–ด ์ดํ•ด

  • ๋ฐฉํ–ฅ: ๋‹จ๋ฐฉํ–ฅ, ์–‘๋ฐฉํ–ฅ
  • ๋‹ค์ค‘์„ฑ: ๋‹ค๋Œ€์ผ, ์ผ๋Œ€๋‹ค, ์ผ๋Œ€์ผ, ๋‹ค๋Œ€๋‹ค
  • ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ: ๊ฐ์ฒด ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋Š” ๊ด€๋ฆฌ ์ฃผ์ธ์ด ํ•„์š”

์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 


์˜ˆ์ œ ์‹œ๋‚˜๋ฆฌ์˜ค

  • ํšŒ์›๊ณผ ํŒ€์ด ์žˆ๋‹ค.
  • ํšŒ์›์€ ํ•˜๋‚˜์˜ ํŒ€์—๋งŒ ์†Œ์†๋  ์ˆ˜ ์žˆ๋‹ค.
  • ํšŒ์›๊ณผ ํŒ€์€ ๋‹ค๋Œ€์ผ ๊ด€๊ณ„๋‹ค.

๊ฐ์ฒด๋ฅผ ํ…Œ์ด๋ธ”์— ๋งž์ถ”์–ด ๋ชจ๋ธ๋ง

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;
    @Column(name = "USERNAME")
    private String name;
    @Column(name = "TEAM_ID")
    private Long teamId;
    โ€ฆ
}
@Entity
public class Team {
    @Id @GeneratedValue
    private Long id;
    private String name;
    โ€ฆ
}
// ํŒ€ ์ €์žฅ
Team team = new Team();
team.setName("TeamA");
em.persist(team);
// ํšŒ์› ์ €์žฅ
Member member = new Member();
member.setName("member1");
member.setTeamId(team.getId());
em.persist(member);
// ์กฐํšŒ
Member findMember = em.find(Member.class, member.getId());
// ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์—†์Œ
Team findTeam = em.find(Team.class, team.getId());

๊ฐ์ฒด๋ฅผ ํ…Œ์ด๋ธ”์— ๋งž์ถ”์–ด ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ์œผ๋กœ ๋ชจ๋ธ๋งํ•˜๋ฉด, ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค. ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค๋กœ ์กฐ์ธ์„ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๋œ ํ…Œ์ด๋ธ”์„ ์ฐพ๋Š” ๋ฐ˜๋ฉด, ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ์ฐพ๋Š”๋‹ค. ํ…Œ์ด๋ธ”๊ณผ ๊ฐ์ฒด ์‚ฌ์ด์—๋Š” ์ด๋Ÿฐ ํฐ ๊ฐ„๊ฒฉ์ด ์กด์žฌํ•œ๋‹ค.

๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„


๊ฐ์ฒด ์ง€ํ–ฅ ๋ชจ๋ธ๋ง

@Entity
public class Member {
    @Id @GeneratedValue
    private Long id;
    @Column(name = "USERNAME")
    private String name;
    private int age;
    // @Column(name = "TEAM_ID")
    // private Long teamId;
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    โ€ฆ
}

//ํŒ€ ์ €์žฅ
Team team = new Team();
team.setName("TeamA");
em.persist(team);
//ํšŒ์› ์ €์žฅ
Member member = new Member();
member.setName("member1");
member.setTeam(team); //๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •, ์ฐธ์กฐ ์ €์žฅ
em.persist(member);
//์กฐํšŒ
Member findMember = em.find(Member.class, member.getId());
//์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๊ด€๊ณ„ ์กฐํšŒ
Team findTeam = findMember.getTeam();
// ์ƒˆ๋กœ์šด ํŒ€B
Team teamB = new Team();
teamB.setName("TeamB");
em.persist(teamB);
// ํšŒ์›1์— ์ƒˆ๋กœ์šด ํŒ€B ์„ค์ •
member.setTeam(teamB);

์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„์™€ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ 1 - ๊ธฐ๋ณธ


์–‘๋ฐฉํ–ฅ ๋งคํ•‘

๊ฐ์ฒด์˜ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„

๊ฐ์ฒด์˜ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋Š” ์‚ฌ์‹ค ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋กœ ๋‹ค๋ฅธ ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„ 2๊ฐœ๋‹ค. ๊ฐ์ฒด๋ฅผ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์ฐธ์กฐํ•˜๋ ค๋ฉด ๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ 2๊ฐœ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

  • ํšŒ์› โ†’ ํŒ€ member.getTeam()
  • ํŒ€ โ†’ ํšŒ์› team.getMembers()

ํ…Œ์ด๋ธ”์˜ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„

ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ๋‘ ํ…Œ์ด๋ธ”์˜ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. MEMBER.TEAM_ID ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๊ฐ€์ง„๋‹ค.

  • ํšŒ์› โ† โ†’ ํŒ€
    • SELECT * FROM MEMBER M JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
    • SELECT * FROM TEAM T JOIN MEMBER M ON T.TEAM_ID = M.TEAM_ID

๋‘˜ ์ค‘ ํ•˜๋‚˜๋กœ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•จ

Member ์˜ Team ์ด๋‚˜ Team ์˜ members ์ค‘์— ์–ด๋–ค ๊ฐ’์ด ๋ฐ”๋€” ๋•Œ MEMBER.TEAM_ID ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์•ผ ํ•˜๋Š”๊ฐ€? ๋‘˜ ์ค‘์— ํ•˜๋‚˜๊ฐ€ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•˜๋„๋ก ์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด๋‹ค.

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ

๊ฐ์ฒด์˜ ๋‘ ๊ด€๊ณ„ ์ค‘ ํ•˜๋‚˜๋ฅผ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์œผ๋กœ ์ง€์ •ํ•œ๋‹ค. ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ๋งŒ์ด ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ฃผ์ธ์ด ์•„๋‹Œ์ชฝ์€ ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

  • ์ฃผ์ธ์€ mappedBy ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ฃผ์ธ์ด ์•„๋‹ˆ๋ฉด mappedBy ์†์„ฑ์œผ๋กœ ์ฃผ์ธ์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ๋ˆ„๊ตฌ๋ฅผ ์ฃผ์ธ์œผ๋กœ ์ •ํ•ด์•ผํ•ด?

์™ธ๋ž˜ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ณณ์„ ์ฃผ์ธ์œผ๋กœ ์ •ํ•ด์•ผํ•œ๋‹ค. DB ์—์„œ ManyToOne ๊ด€๊ณ„์ผ ๊ฒฝ์šฐ, ํ•ญ์ƒ FK ๋ฅผ ๊ฐ–๋Š” ์ชฝ์€ Many ๊ฐ€ ๋˜๊ธฐ ๋•Œ๋ฌธ์—, Many ์ชฝ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๋˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์œ„ ์˜ˆ์‹œ์—์„œ๋Š” Member ์˜ Team ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ์‹œ ๊ฐ€์žฅ ๋งŽ์ด ํ•˜๋Š” ์‹ค์ˆ˜

Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
// ์—ญ๋ฐฉํ–ฅ(์ฃผ์ธ์ด ์•„๋‹Œ ๋ฐฉํ–ฅ)๋งŒ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •
team.getMembers().add(member);
em.persist(member);

์œ„ ์ฝ”๋“œ ์‹คํ–‰ ์‹œ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’์„ ์ž…๋ ฅํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— member ์˜ team ์€ null ์ด ๋œ๋‹ค.

Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
member.setTeam(team); // ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์—๋งŒ ๊ฐ’ ์„ค์ •
em.persist(member);
team.getMembers(); // null

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์—๋งŒ ๊ฐ’์„ ๋„ฃ์–ด์ค€๋‹ค๋ฉด, JPA ์— ์˜ํ•ด mappedBy ์ชฝ์—์„œ๋„ ๊ฐ’์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์ง€๋งŒ, 2๊ฐ€์ง€ ๋ฌธ์ œ์ ์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

  1. em.flush() ์ดํ›„ em.clear() ๋ฅผ ํ•œ ๋’ค DB ์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜จ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ, ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— Team ๊ณผ Member ๋ฅผ ์ €์žฅํ•œ ๋’ค ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, team.getMembers() ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด null ๊ฐ’์ด ๋ฐ˜ํ™˜๋œ๋‹ค.
  2. ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๋Š” ๋Œ€๋ถ€๋ถ„ JPA ์—†์ด ์ˆœ์ˆ˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ด๋ฃจ์–ด์ง€๋Š”๋ฐ, ์ด๋Ÿด ๊ฒฝ์šฐ null ์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์˜

Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
member.setTeam(team); // ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’ ์„ค์ •
em.persist(member);
team.getMembers().add(member); // ์—ญ๋ฐฉํ–ฅ์—๋„ ๊ฐ’ ์„ค์ •
  1. ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ 2๊ฐ€์ง€ ๋ฌธ์ œ์ ๊ณผ ๋”๋ถˆ์–ด, ์‚ฌ์šฉ๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ด์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์ ์ด๋ฉด ์œ„ ์ฝ”๋“œ ์ฒ˜๋Ÿผ ์–‘์ชฝ์— ๊ฐ’์„ ๋‹ค ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
public void changeTeam(Team team) {
    this.team = team;
    team.getMembers().add(this);
}
  1. ๋˜ํ•œ, ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ • ์‹œ ์–‘์ชฝ์— ๋ชจ๋‘ ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์ž.
  2. ์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ์‹œ toString() ์™€ JSON ์ƒ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ์‹œ member ์˜ team ์„ ์ฐธ์กฐํ•˜๊ณ  team ์˜ member ๋ฅผ ์ฐธ์กฐํ•˜๋ฉด์„œ ๋ฌดํ•œ ๋ฃจํ”„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ€๊ธ‰์ ์ด๋ฉด toString() ์„ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ณ  Controller ์—๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ ˆ๋Œ€ ๋ฐ˜ํ™˜ํ•˜์ง€ ์•Š๋„๋ก ํ•˜์ž. Controller ๊ฐ€ DTO ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์œ ๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ๋‹ค.

์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ์ •๋ฆฌ

  • ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๋งŒ์œผ๋กœ๋„ ์ด๋ฏธ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘์€ ์™„๋ฃŒ๋œ ๊ฒƒ์ด๋‹ค.
  • ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์€ ๋ฐ˜๋Œ€ ๋ฐฉํ–ฅ์œผ๋กœ ์กฐํšŒ(๊ฐ์ฒด ํƒ์ƒ‰ ๊ทธ๋ž˜ํ”„) ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋œ ๊ฒƒ ๋ฟ์ด๋‹ค.
  • JPQL ์—์„œ ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ํƒ์ƒ‰ํ•  ์ผ์ด ๋งŽ๋‹ค.
  • ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘์„ ์ž˜ ํ•˜๊ณ  ์–‘๋ฐฉํ–ฅ์€ ํ•„์š”ํ•  ๋•Œ ์ถ”๊ฐ€ํ•ด๋„ ๋œ๋‹ค. ํ…Œ์ด๋ธ”์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š”๋‹ค.

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์„ ์ •ํ•˜๋Š” ๊ธฐ์ค€

  • ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์€ ์™ธ๋ž˜ ํ‚ค์˜ ์œ„์น˜๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ •ํ•ด์•ผํ•œ๋‹ค.

์‹ค์ „ ์˜ˆ์ œ 2 - ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ ์‹œ์ž‘


ํ…Œ์ด๋ธ” ๊ตฌ์กฐ

ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋Š” ์ด์ „๊ณผ ๊ฐ™๋‹ค.

๊ฐ์ฒด ๊ตฌ์กฐ

์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณ€๊ฒฝํ•œ๋‹ค.

์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ ์‹œ ๊ณ ๋ ค์‚ฌํ•ญ 3๊ฐ€์ง€


๋‹ค์ค‘์„ฑ

  • @ManyToOne ๋‹ค๋Œ€์ผ
  • @OneToMany ์ผ๋Œ€๋‹ค
  • @OneToOne ์ผ๋Œ€์ผ
  • @ManyToMany ๋‹ค๋Œ€๋‹ค

๋‹จ๋ฐฉํ–ฅ, ์–‘๋ฐฉํ–ฅ

ํ…Œ์ด๋ธ”

  • ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ์–‘์ชฝ ์กฐ์ธ ๊ฐ€๋Šฅ
  • ์‚ฌ์‹ค ๋ฐฉํ–ฅ์ด๋ผ๋Š” ๊ฐœ๋…์ด ์—†์Œ ๊ฐ์ฒด
  • ์ฐธ์กฐ์šฉ ํ•„๋“œ๊ฐ€ ์žˆ๋Š” ์ชฝ์œผ๋กœ๋งŒ ์ฐธ์กฐ ๊ฐ€๋Šฅ
  • ํ•œ์ชฝ๋งŒ ์ฐธ์กฐํ•˜๋ฉด ๋‹จ๋ฐฉํ–ฅ
  • ์–‘์ชฝ์ด ์„œ๋กœ ์ฐธ์กฐํ•˜๋ฉด ์–‘๋ฐฉํ–ฅ

์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ

  • ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ๋‘ ํ…Œ์ด๋ธ”์ด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ์Œ
  • ๊ฐ์ฒด ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋Š” ์ฐธ์กฐ๊ฐ€ 2๊ตฐ๋ฐ ์žˆ์Œ
  • ๋‘˜ ์ค‘ ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•  ๊ณณ์„ ์ง€์ •ํ•ด์•ผ ํ•จ
  • ์ฆ‰, ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์€ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฐธ์กฐ์ด๊ณ , ์ฃผ์ธ์˜ ๋ฐ˜๋Œ€ํŽธ์€ ๋‹จ์ˆœ ์กฐํšŒ๋งŒ ๊ฐ€๋Šฅ

๋‹ค๋Œ€์ผ [N:1]


๋‹ค๋Œ€์ผ ๋‹จ๋ฐฉํ–ฅ

  • ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„
  • ๋‹ค๋Œ€์ผ์˜ ๋ฐ˜๋Œ€๋Š” ์ผ๋Œ€๋‹ค

๋‹ค๋Œ€์ผ ์–‘๋ฐฉํ–ฅ

  • ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์žˆ๋Š” ์ชฝ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ
  • ์–‘์ชฝ์„ ์„œ๋กœ ์ฐธ์กฐํ•˜๋„๋ก ๊ฐœ๋ฐœ

์ผ๋Œ€๋‹ค [1:N]


์ผ๋Œ€๋‹ค ๋‹จ๋ฐฉํ–ฅ

๊ฒฐ๋ก ๋ถ€ํ„ฐ ๋งํ•˜์ž๋ฉด ์ด๋Ÿฐ ๊ตฌ์กฐ๋Š” ๊ฑฐ์˜ ๊ฐ€์ ธ๊ฐ€์ง€ ์•Š๋Š”๋‹ค. ์ผ๋Œ€๋‹ค ๋‹จ๋ฑกํ–ฅ์€ ์ผ๋Œ€๋‹ค์—์„œ ์ผ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๋œ๋‹ค. ํ•˜์ง€๋งŒ, ํ…Œ์ด๋ธ” ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์—์„œ๋Š” ํ•ญ์ƒ ๋‹ค์ชฝ์— ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ, ๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ”์˜ ์ฐจ์ด ๋•Œ๋ฌธ์— ๋ฐ˜๋Œ€ํŽธ ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ํŠน์ดํ•œ ๊ตฌ์กฐ๊ฐ€ ๋œ๋‹ค.

Member member = new Member();
member.setUserName("member1");
em.persist(member);
Team team = new Team();
team.setName("teamA");
team.getMembers().add(member);
em.persist(team);

ํ•ด๋‹น ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๊ฒฝ์šฐ, ํ…Œ์ด๋ธ” ์ž…์žฅ์—์„œ๋Š” MEMBER ๊ฐ€ TEAM_ID ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, TEAM ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•ด MEMBER ํ…Œ์ด๋ธ”์— UPDATE ์ฟผ๋ฆฌ๊ฐ€ ์ถ”๊ฐ€๋กœ ๋‚˜๊ฐ€๊ฒŒ ๋œ๋‹ค.

@Entity
public class Team {
    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private String name;
    @OneToMany
    @JoinColumn(name = "TEAM_ID")
    private List<Member> members = new ArrayList<>();
}

๋˜ํ•œ, ์œ„์ฒ˜๋Ÿผ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ๊ฐ–๋Š” ์ปฌ๋Ÿผ์— @JoinColumn ์„ ๊ผญ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด TEAM_ID ์™€ MEMBER_ID ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ค‘๊ฐ„ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•˜์—ฌ ์กฐ์ธ ํ…Œ์ด๋ธ” ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

์ผ๋Œ€๋‹ค ๋‹จ๋ฐฉํ–ฅ ์ •๋ฆฌ

์ผ๋Œ€๋‹ค ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘์˜ ๋‹จ์ 

  • ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” ์™ธ๋ž˜ ํ‚ค๊ฐ€ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”์— ์žˆ์Œ
  • ์—ฐ๊ด€๊ด€๊ณ„ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด ์ถ”๊ฐ€๋กœ UPDATE SQL ์‹คํ–‰ ๋•Œ๋ฌธ์—, ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ์†ํ•ด๋ฅผ ๋ณด๋”๋ผ๋„ ์ผ๋Œ€๋‹ค ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๋ณด๋‹ค๋Š” ๋‹ค๋Œ€์ผ ์–‘๋ฐฉํ–ฅ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ด€๊ณ„๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ฒƒ์ด ๋” ์ข‹์€ ์„ค๊ณ„์ผ ์ˆ˜ ์žˆ๋‹ค.

์ผ๋Œ€๋‹ค ์–‘๋ฐฉํ–ฅ

์ด๋Ÿฐ ๋งคํ•‘์€ ๊ณต์‹์ ์œผ๋กœ ์กด์žฌํ•˜์ง€ ์•Š์ง€๋งŒ ๋งŒ๋“ค ์ˆ˜๋Š” ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ, @JoinColumn(insertable=false, updatable=false) ๋กœ ์ฝ๊ธฐ ์ „์šฉ ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์–‘๋ฐฉํ–ฅ ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Ÿฐ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ๋‹ค๋Œ€์ผ ์–‘๋ฐฉํ–ฅ ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

์ผ๋Œ€์ผ [1:1]


์ผ๋Œ€์ผ ๊ด€๊ณ„

์ผ๋Œ€์ผ ๊ด€๊ณ„๋Š” ๊ทธ ๋ฐ˜๋Œ€๋„ ์ผ๋Œ€์ผ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€์นญ ๊ด€๊ณ„๋ผ๊ณ  ์ƒ๊ฐํ•ด๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋•Œ๋ฌธ์—, ์ฃผ ํ…Œ์ด๋ธ”์ด๋‚˜ ๋Œ€์ƒ ํ…Œ์ด๋ธ” ์ค‘์— ํ•œ ๊ณณ์—์„œ ์™ธ๋ž˜ ํ‚ค๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋‹ค. ํ…Œ์ด๋ธ” ๊ด€์ ์—์„œ ์ผ๋Œ€์ผ ๊ด€๊ณ„๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„  ์™ธ๋ž˜ ํ‚ค์— UNI ์ œ์•ฝ์กฐ๊ฑด์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•œ๋‹ค.

์ฃผ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค ๋‹จ๋ฐฉํ–ฅ

@ManyToOne ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๊ณผ ์œ ์‚ฌํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ฃผ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค ์–‘๋ฐฉํ–ฅ

๋‹ค๋Œ€์ผ ์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ์ฒ˜๋Ÿผ ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ณณ์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๋˜๋ฉฐ, ๋ฐ˜๋Œ€ํŽธ์€ mappedBy ๋ฅผ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๋Œ€์ƒ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค ๋‹จ๋ฐฉํ–ฅ

๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„๋Š” JPA ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š์ง€๋งŒ, ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋Š” ์ง€์›ํ•œ๋‹ค. MEMBER ํ…Œ์ด๋ธ”์„ ๋งŽ์ด SELECT ํ•œ๋‹ค๋Š” ๊ฐ€์ •ํ•˜์—, MEMBER ๊ฐ€ LOCKER ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ด๋‹ค.

๋Œ€์ƒ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค ์–‘๋ฐฉํ–ฅ

์‚ฌ์‹ค ์ผ๋Œ€์ผ ์ฃผ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค ์–‘๋ฐฉํ–ฅ๊ณผ ๋งคํ•‘ ๋ฐฉ๋ฒ•์€ ๊ฐ™๋‹ค.

์ผ๋Œ€์ผ ์ •๋ฆฌ

์ฃผ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค๋ฅผ ์œ„์น˜์‹œํ‚ค๋ฉด, ์ฃผ ๊ฐ์ฒด๊ฐ€ ๋Œ€์ƒ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ ์ฒ˜๋Ÿผ ์ฃผ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค๋ฅผ ๋‘๊ณ  ๋Œ€์ƒ ํ…Œ์ด๋ธ”์„ ์ฐพ์„ ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๊ฐ์ฒด์ง€ํ–ฅ ๊ฐœ๋ฐœ์ž๋“ค์ด ์„ ํ˜ธํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋ฉฐ, JPA ๋งคํ•‘์ด ํŽธ๋ฆฌํ•˜๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค. ์ฃผ ํ…Œ์ด๋ธ”๋งŒ ์กฐํšŒํ•ด๋„ ๋Œ€์ƒ ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์ง€๋งŒ, ๊ฐ’์ด ์—†์œผ๋ฉด ์™ธ๋ž˜ ํ‚ค์— null ์„ ํ—ˆ์šฉํ•œ๋‹ค๋Š” ๋‹จ์  ์—ญ์‹œ ์กด์žฌํ•œ๋‹ค. ๋Œ€์ƒ ํ…Œ์ด๋ธ”์— ์™ธ๋ž˜ ํ‚ค๋ฅผ ์œ„์น˜์‹œํ‚ค๋ฉด, ์ฃผ ํ…Œ์ด๋ธ”๊ณผ ๋Œ€์ƒ ํ…Œ์ด๋ธ”์„ ์ผ๋Œ€์ผ์—์„œ ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ ๋‹ค์ชฝ์ด ๋˜๋Š” ํ…Œ์ด๋ธ”์— ์ด๋ฏธ ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ํ…Œ์ด๋ธ” ๊ตฌ์กฐ๋ฅผ ์œ ์ง€ํ•˜๊ณ  ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์žฅ์ ์ด ์กด์žฌํ•œ๋‹ค. ํ•˜์ง€๋งŒ, ํ”„๋ก์‹œ ๊ธฐ๋Šฅ์˜ ํ•œ๊ณ„๋กœ ์ง€์—ฐ ๋กœ๋”ฉ์œผ๋กœ ์„ค์ •ํ•ด๋„ ํ•ญ์ƒ ์ฆ‰์‹œ ๋กœ๋”ฉ๋˜๋Š” ๋‹จ์  ์—ญ์‹œ ์กด์žฌํ•œ๋‹ค.

๋‹ค๋Œ€๋‹ค [N:M]


๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ •๊ทœํ™”๋œ ํ…Œ์ด๋ธ” 2๊ฐœ๋กœ ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์—ฐ๊ฒฐ ํ…Œ์ด๋ธ”์„ ์ถ”๊ฐ€ํ•ด์„œ ์ผ๋Œ€๋‹ค, ๋‹ค๋Œ€์ผ ๊ด€๊ณ„๋กœ ํ’€์–ด๋‚ด์•ผ ํ•œ๋‹ค. ๊ฐ์ฒด๋Š” ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•ด์„œ ๊ฐ์ฒด 2๊ฐœ๋กœ ๋‹ค๋Œ€๋‹ค ๊ด€๊ณ„๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. @ManyToMany ์™€ @JoinTable ๋กœ ์—ฐ๊ฒฐ ํ…Œ์ด๋ธ”์„ ์ง€์ •ํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

๋‹ค๋Œ€๋‹ค ๋งคํ•‘์˜ ํ•œ๊ณ„

ํŽธ๋ฆฌํ•ด ๋ณด์ด์ง€๋งŒ ์‹ค๋ฌด์—์„œ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์—ฐ๊ฒฐ ํ…Œ์ด๋ธ”์ด ๋‹จ์ˆœํžˆ ์—ฐ๊ฒฐ๋งŒ ํ•˜๊ณ  ๋๋‚˜์ง€ ์•Š๊ณ , ์ฃผ๋ฌธ์‹œ๊ฐ„, ์ˆ˜๋Ÿ‰ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋Œ€๋‹ค ํ•œ๊ณ„ ๊ทน๋ณต

์—ฐ๊ฒฐ ํ…Œ์ด๋ธ”์„ ์—”ํ‹ฐํ‹ฐ๋กœ ์Šน๊ฒฉ์‹œ์ผœ ์—ฐ๊ฒฐ ํ…Œ์ด๋ธ”์šฉ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค. @ManyToMany โ†’ @OneToMany @ManyToOne

์‹ค์ „ ์˜ˆ์ œ 3 - ๋‹ค์–‘ํ•œ ์—ฐ๊ด€๊ฐ„๊ณ„ ๋งคํ•‘


N:M ๊ด€๊ณ„๋Š” 1:N, N:1 ๋กœ ๋ณ€๊ฒฝ

ํ…Œ์ด๋ธ”์˜ N:M ๊ด€๊ณ„๋Š” ์ค‘๊ฐ„ ํ…Œ์ด๋ธ”์„ ์ด์šฉํ•ด์„œ 1:N, N:1 ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์‹ค์ „์—์„œ๋Š” ์ค‘๊ฐ„ ํ…Œ์ด๋ธ”์ด ๋‹จ์ˆœํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— N:M ์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

@JoinColumn

์™ธ๋ž˜ ํ‚ค๋ฅผ ๋งคํ•‘ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

  • name ๋งคํ•‘ํ•  ์™ธ๋ž˜ ํ‚ค ์ด๋ฆ„
  • referencedColumnName ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์ƒ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋ช…
  • foreignKey(DDL) ์™ธ๋ž˜ ํ‚ค ์ œ์•ฝ์กฐ๊ฑด์„ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Œ
  • unique nullable insertable updatable columnDefinition table @Column ์˜ ์†์„ฑ๊ณผ ๊ฐ™์Œ

@ManyToOne

๋‹ค๋Œ€์ผ ๊ด€๊ณ„ ๋งคํ•‘ ์‹œ ์‚ฌ์šฉํ•œ๋‹ค.

  • optional false ๋กœ ์„ค์ • ์‹œ ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ•ญ์ƒ ์žˆ์–ด์•ผ ํ•จ
  • fetch ๊ธ€๋กœ๋ฒŒ ํŽ˜์น˜ ์ „๋žต์„ ์„ค์ •
  • cascade ์˜์†์„ฑ ์ „์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ
  • targetEntity ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž… ์ •๋ณด๋ฅผ ์„ค์ •. ์ œ๋„ค๋ฆญ์œผ๋กœ ํƒ€์ž… ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

@OneToMany

๋‹ค๋Œ€์ผ ๊ด€๊ณ„ ๋งคํ•‘ ์‹œ ์‚ฌ์šฉํ•œ๋‹ค.

  • mappedBy ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ ํ•„๋“œ๋ฅผ ์„ ํƒ
  • fetch ๊ธ€๋กœ๋ฒŒ ํŽ˜์น˜ ์ „๋žต์„ ์„ค์ •
  • cascade ์˜์†์„ฑ ์ „์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉ
  • targetEntity ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ ํƒ€์ž… ์ •๋ณด๋ฅผ ์„ค์ •. ์ œ๋„ค๋ฆญ์œผ๋กœ ํƒ€์ž… ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ฑฐ์˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ

์ƒ์†๊ด€๊ณ„ ๋งคํ•‘


๊ฐ์ฒด๋Š” ์ƒ์†๊ด€๊ณ„๊ฐ€ ์žˆ์ง€๋งŒ RDB ์—๋Š” ์ƒ์†๊ด€๊ณ„๊ฐ€ ์—†๋‹ค. RDB ์˜ ์Šˆํผํƒ€์ž… ์„œ๋ธŒํƒ€์ž… ๊ด€๊ณ„๋ผ๋Š” ๋ชจ๋ธ๋ง ๊ธฐ๋ฒ•์ด ๊ฐ์ฒด์˜ ์ƒ์†๊ณผ ์œ ์‚ฌํ•˜๋‹ค. ์ฆ‰, ์ƒ์†๊ด€๊ณ„ ๋งคํ•‘์ด๋ž€, ๊ฐ์ฒด์˜ ์ƒ์†๊ตฌ์กฐ์™€ RDB ์˜ ์Šˆํผํƒ€์ž… ์„œ๋ธŒํƒ€์ž… ๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค. ์Šˆํผํƒ€์ž… ์„œ๋ธŒํƒ€์ž… ๋…ผ๋ฆฌ ๋ชจ๋ธ์„ ์‹ค์ œ ๋ฌผ๋ฆฌ ๋ชจ๋ธ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฒ•์€ ์ด 3๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•œ๋‹ค.

  1. ์กฐ์ธ ์ „๋žต
  2. ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต
  3. ๊ตฌํ˜„ ํด๋ž˜์Šค๋งˆ๋‹ค ํ…Œ์ด๋ธ” ์ „๋žต

์กฐ์ธ ์ „๋žต

@Inheritance*(*strategy = InheritanceType.JOINED*)* @DiscriminatorColumn(name = "DTYPE") ๊ธฐ๋ณธ๊ฐ’์€ โ€œDTYPEโ€ ์ด๋ฉฐ, ์ž์‹ ํ…Œ์ด๋ธ”์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•ด DTYPE ์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. @DiscriminatorValue("XXX") ๊ธฐ๋ณธ๊ฐ’์€ โ€œํด๋ž˜์Šค๋ช…โ€ ์ด๋ฉฐ, ์ž์‹ ํ…Œ์ด๋ธ”์˜ ํ…Œ์ด๋ธ”๋ช…์„ ๋ช…์‹œํ•ด์ฃผ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์กฐ์ธ ์ „๋žต์˜ ์žฅ์ ์œผ๋กœ๋Š”, ํ…Œ์ด๋ธ”์ด ์ •๊ทœํ™” ๋˜์–ด์žˆ๊ณ , ์™ธ๋ž˜ ํ‚ค ์ฐธ์กฐ ๋ฌด๊ฒฐ์„ฑ ์ œ์•ฝ์กฐ๊ฑด์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ํšจ์œจ์ ์œผ๋กœ ์ €์žฅ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค. ๋ฐ˜๋ฉด, ๋‹จ์ ์œผ๋กœ๋Š”, ์กฐํšŒ ์‹œ ์กฐ์ธ์„ ๋งŽ์ด ์‚ฌ์šฉ๋˜์–ด ์„ฑ๋Šฅ์ด ์ €ํ•˜๋˜๊ณ , ๋ฐ์ดํ„ฐ ์ €์žฅ ์‹œ INSERT ์ฟผ๋ฆฌ๊ฐ€ 2๋ฒˆ ํ˜ธ์ถœ๋˜๋Š” ์ ์ด ์žˆ๋‹ค. ๊ฐ์ฒด์˜ ์ƒ์†๊ณผ ๊ฐ€์žฅ ์œ ์‚ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋ณธ์ ์œผ๋ก , ์กฐ์ธ ์ „๋žต์ด ์ •์„์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต

@Inheritance*(*strategy = InheritanceType.SINGLE_TABLE*)* ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต์€ ๋ชจ๋“  ์ž์‹ ํ…Œ์ด๋ธ” ์š”์†Œ๋ฅผ ํ•œ ํ…Œ์ด๋ธ”์—์„œ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ž์‹ ํ…Œ์ด๋ธ”์„ ๊ตฌ๋ถ„ํ•˜๊ธฐ ์œ„ํ•˜์—ฌDTYPE ๋ฅผ ์ž๋™์œผ๋กœ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค. ๋‹จ์ผ ํ…Œ์ด๋ธ” ์ „๋žต์˜ ์žฅ์ ์œผ๋กœ๋Š”, ์กฐ์ธ์ด ํ•„์š” ์—†๊ธฐ์— ์ผ๋ฐ˜์ ์œผ๋กœ ์กฐํšŒ๊ฐ€ ๋น ๋ฅด๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค. ๋ฐ˜๋ฉด, ๋‹จ์ ์œผ๋กœ๋Š”, ์ž์‹ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๋งคํ•‘ํ•œ ์ปฌ๋Ÿผ์€ ๋ชจ๋‘ null ์„ ํ—ˆ์šฉํ•ด์•ผํ•˜๋ฉฐ, ๋‹จ์ผ ํ…Œ์ด๋ธ”์— ๋ชจ๋“  ๊ฒƒ์„ ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ƒํ™ฉ์— ๋”ฐ๋ผ ์กฐํšŒ ์„ฑ๋Šฅ์ด ์˜คํžˆ๋ ค ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žˆ๋‹ค.

๊ตฌํ˜„ ํด๋ž˜์Šค๋งˆ๋‹ค ํ…Œ์ด๋ธ” ์ „๋žต

@Inheritance*(*strategy = InheritanceType.TABLE_PER_CLASS*)* ๋ถ€๋ชจ ํ…Œ์ด๋ธ”์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— Item ํƒ€์ž…์œผ๋กœ ์กฐํšŒ ์‹œ ๋ชจ๋“  ์ž์‹ ํ…Œ์ด๋ธ”์„ ๋’ค์ ธ์„œ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ๋Š”๋‹ค. ์ด ์ „๋žต์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

@MappedSuperclass - ๋งคํ•‘ ์ •๋ณด ์ƒ์†


@MappedSuperclass
public abstract class BaseEntity {
    private String createdBy;
    private LocalDateTime createdDate;
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;
}

๊ณตํ†ต ๋งคํ•‘ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰, ์†์„ฑ๋งŒ ์ƒ์†๋ฐ›์•„์„œ ์“ฐ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ํ…Œ์ด๋ธ”๊ณผ ๊ด€๊ณ„ ์—†์ด ๋‹จ์ˆœํžˆ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ๊ณตํ†ต์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋งคํ•‘ ์ •๋ณด๋ฅผ ๋ชจ์œผ๋Š” ์—ญํ• ์ด๋‹ค. ์ฃผ๋กœ ๋“ฑ๋ก์ผ, ์ˆ˜์ •์ผ, ๋“ฑ๋ก์ž, ์ˆ˜์ •์ž ๊ฐ™์€ ์ „์ฒด ์—”ํ‹ฐํ‹ฐ์—์„œ ๊ณตํ†ต์œผ๋กœ ์ ์šฉํ•˜๋Š” ์ •๋ณด๋ฅผ ๋ชจ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์ง์ ‘ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•  ์ผ์ด ๊ฑฐ์˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๊ถŒ์žฅํ•œ๋‹ค.

์‹ค์ „ ์˜ˆ์ œ 4 - ์ƒ์†๊ด€๊ณ„ ๋งคํ•‘


๋„๋ฉ”์ธ ๋ชจ๋ธ