์ง€์€์ด์˜ ๊ฐœ๋ฐœ Blog

JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - 5์žฅ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘ ๊ธฐ์ดˆ

August 11, 2022 โ€ข โ˜•๏ธโ˜•๏ธ 12 min read

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

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

๋ฐฉํ–ฅ(Direction)

  • [๋‹จ๋ฐฉํ–ฅ, ์–‘๋ฐฉํ–ฅ]
  • ํšŒ์› โ†’ ํŒ€ ๋˜๋Š” ํŒ€ โ†’ ํšŒ์› ์ฒ˜๋Ÿผ ๋‘˜ ์ค‘ ํ•œ ์ชฝ๋งŒ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์„ ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„๋ผ๊ณ  ํ•œ๋‹ค.
  • ํšŒ์› <-> ํŒ€ ์ฒ˜๋Ÿผ ์„œ๋กœ ์ฐธ์กฐํ•˜๋Š” ๊ฒƒ์„ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋ผ๊ณ  ํ•œ๋‹ค.
  • ๋ฐฉํ–ฅ์€ ๊ฐ์ฒด๊ด€๊ณ„์—๋งŒ ์กด์žฌํ•˜๊ณ  ํ…Œ์ด๋ธ” ๊ด€๊ณ„๋Š” ํ•ญ์ƒ ์–‘๋ฐฉํ–ฅ์ด๋‹ค.

๋‹ค์ค‘์„ฑ(Multiplicity)

  • [๋‹ค๋Œ€์ผ(N:1), ์ผ๋Œ€๋‹ค(1:N), ์ผ๋Œ€์ผ(1:1), ๋‹ค๋Œ€๋‹ค(N:M)]

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

  • ๊ฐ์ฒด๋ฅผ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋กœ ๋งŒ๋“ค๋ฉด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ์žˆ์–ด์•ผ ํ•œ๋‹ค.

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

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

๋‹ค๋Œ€์ผ(N:1) ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„

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

Untitled

๊ฐ์ฒด ์—ฐ๊ด€๊ด€๊ณ„

  • ํšŒ์› ๊ฐ์ฒด๋Š” Member.team ํ•„๋“œ(๋ฉค๋ฒ„๋ณ€์ˆ˜)๋กœ ํŒ€ ๊ฐ์ฒด์™€ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค.
  • ํšŒ์›๊ณผ ํŒ€ ๊ฐ์ฒด๋Š”ย ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„๋‹ค. ํšŒ์›์€ Member.team ํ•„๋“œ๋ฅผ ํ†ตํ•ด์„œ ํŒ€์„ ์•Œ ์ˆ˜ ์žˆ์ง€๋งŒ ๋ฐ˜๋Œ€๋กœ ํŒ€์€ ํšŒ์›์„ ์•Œ ์ˆ˜ ์—†๋‹ค.

ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„

  • ํšŒ์› ํ…Œ์ด๋ธ”์€ TEAM_ID ์™ธ๋ž˜ ํ‚ค๋กœ ํŒ€ ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค.
  • ํšŒ์› ํ…Œ์ด๋ธ”๊ณผ ํŒ€ ํ…Œ์ด๋ธ”์€ย ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋‹ค. ํšŒ์› ํ…Œ์ด๋ธ”์˜ TEAM_ID ์™ธ๋ž˜ ํ‚ค๋ฅผ ํ†ตํ•ด์„œ ํšŒ์›๊ณผ ํŒ€์„ ์กฐ์ธํ•  ์ˆ˜ ์žˆ๊ณ  ๋ฐ˜๋Œ€๋กœ ํŒ€๊ณผ ํšŒ์›๋„ ์กฐ์ธํ•  ์ˆ˜ ์žˆ๋‹ค.
SELECT *
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.ID;
SELECT *
FROM TEAM T
JOIN MEMBER M ON  T.TEAM_ID = M.TEAM_ID;

๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ”์˜ ๋‹ค๋ฅธ ์ 

  • ์ฐธ์กฐ๋ฅผ ํ†ตํ•œ ์—ฐ๊ด€๊ฐ„๊ณ„๋Š” ์–ธ์ œ๋‚˜ ๋‹จ๋ฐฉํ–ฅ์ด๋‹ค. ๊ฐ์ฒด๊ฐ„์— ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์œผ๋ฉด ๋ฐ˜๋Œ€์ชฝ์—๋„ ํ•„๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์„œ ์ฐธ์กฐ๋ฅผ ๋ณด๊ด€ํ•ด์•ผ ํ•œ๋‹ค.
  • ์ •ํ™•ํžˆ ์ด์•ผ๊ธฐํ•˜๋ฉด ์ด๊ฒƒ์€ย ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๊ฐ€ ์•„๋‹ˆ๋ผ ์„œ๋กœ ๋‹ค๋ฅธ ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„ 2๊ฐœ๋‹ค.
  • ๋ฐ˜๋ฉด์— ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์กฐ์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ์ฒด๋Š” ์ฐธ์กฐ(์ฃผ์†Œ)๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค. (a.getB().getC())

ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ํ‚ค๋กœ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š”๋‹ค. (A JOIN B AND B JOIN A)

5.1.1. ์ˆœ์ˆ˜ํ•œ ๊ฐ์ฒด ์—ฐ๊ด€๊ด€๊ณ„

public class Member {
    private String id;
    private String username;

    @Getter
    @Setter
    private Team team; //ํŒ€์˜ ์ฐธ์กฐ๋ฅผ ๋ณด๊ด€
}
@Getter
@Setter
public class Team {
    private String id;
    private String name;
}

Team team1 = new Team("team1", "ํŒ€1");

Member member1 = new Member("member1", "ํšŒ์›1");
Member member2 = new Member("member2", "ํšŒ์›2");

member1.setTeam(team);
member2.setTeam(team);

Team findTeam = member1.getTeam();

ํšŒ์›1์ด ์†ํ•œ ํŒ€ 1์„ ์กฐํšŒํ•ด๋ณด์ž

Team findTeam = member1.getTeam();

์ด์ฒ˜๋Ÿผ ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์ด๊ฒƒ์„ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰์ด๋ผํ•œ๋‹ค.

5.1.2. ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„

CREATE TABLE MEMBER (
    MEMBER_ID VARCHAR(255) NOT NULL,
    TEAM_ID VARCHAR(255),
    USERNAME VARCHAR(255),
    PRIMARY KEY (MEMBER_ID)
)
CREATE TABLE TEAM (
    TEAM_ID VARCHAR(255) NOT NULL,
    NAME VARCHAR(255),
    PRIMARY KEY (TEAM_ID)
)
ALTER TABLE MEMBER ADD CONSTRAINT FK_MEMBER_TEAM
    FOREIGN KEY (TEAM_ID) REFERENCES TEAM;

์ด๋Ÿฐ ํ…Œ์ด๋ธ” ๊ตฌ์กฐ์—์„œ member1 ์ด๋ผ๋Š” ID๋ฅผ ๊ฐ€์ง„ ๋ฉค๋ฒ„์˜ ํŒ€์„ ๊ฐ™์ด ์กฐํšŒํ•ด๋ณด์ž.

SELECT T.* 
FROM MEMBER M
		JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
WHERE M.MEMBER_ID = 'member1'

์ด์ฒ˜๋Ÿผ ์™ธ๋ž˜ํ‚ค๋ฅผ ์‚ฌ์šฉํ•ด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ๊ฒƒ์„ ์กฐ์ธ์ด๋ผ๊ณ  ํ•œ๋‹ค.

5.1.3. ๊ฐ์ฒด๊ด€๊ณ„ ๋งคํ•‘

JPA ์ƒ์—์„œ ๋‘˜์„ ๋งคํ•‘ํ•ด๋ณด์ž

@Entity
@Getter
@Setter
pubilc class Member {
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    private String username;

    //์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

@Entity
@Getter
@Setter
pubilc class Team {
    @Id
    @Column(name = "TEAM_ID")
    private String id;

    private String name;
}

๊ฐ์ฒด ์—ฐ๊ด€๊ด€๊ณ„ : [Member.team](http://Member.team) ํ•„๋“œ ์‚ฌ์šฉ

ํ…Œ์ด๋ธ” ์—ฐ๊ด€๊ด€๊ณ„ : MEMBER.TEAM_ID ์™ธ๋ž˜ ํ‚ค ์ปฌ๋Ÿผ ์‚ฌ์šฉ

5.1.4. @JoinColumn

@JoinColumn์„ ์ƒ๋žตํ•˜๋ฉด ์™ธ๋ž˜ํ‚ค๋ฅผ ์ฐพ์„ ์‹œ ๊ธฐ๋ณธ ์ „๋žต์„ ์‚ฌ์šฉํ•œ๋‹ค.

์†์„ฑ ๊ธฐ๋Šฅ ๊ธฐ๋ณธ๊ฐ’
name ๋งคํ•‘ํ•  ์™ธ๋ž˜ ํ‚ค ์ด๋ฆ„ ํ•„๋“œ๋ช… + _ + ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค ์ปฌ๋Ÿผ๋ช…
referencedColumnName ์™ธ๋ž˜ ํ‚ค๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ๋Œ€์ƒ ํ…Œ์ด๋ธ”์˜ ์ปฌ๋Ÿผ๋ช… 8์žฅ ์ฐธ์กฐ ์ฐธ์กฐํ•˜๋Š” ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค ์ปฌ๋Ÿผ๋ช…
foreignKey(DDL) ์™ธ๋ž˜ ํ‚ค ์ œ์•ฝ์กฐ๊ฑด์„ ์ง์ ‘ ์ง€์ •. ํ…Œ์ด๋ธ”์„ ์ƒ์„ฑํ•  ๋•Œ๋งŒ ์‚ฌ์šฉ 8์žฅ ์ฐธ๊ณ 

| unique nullable insertable updatable columnDefinition table | @Column ์†์„ฑ๊ณผ ๊ฐ™์Œ | |

5.1.5 @ManyToOne

์†์„ฑ ๊ธฐ๋Šฅ ๊ธฐ๋ณธ๊ฐ’
optional false๋กœ ์„ค์ •ํ•˜๋ฉด ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๊ฐ€ ํ•ญ์ƒ ์žˆ์–ด์•ผ ํ•œ๋‹ค true
fetch ๊ธ€๋กœ๋ฒŒ ํŽ˜์น˜ ์ „๋žต์„ ์„ค์ •ํ•œ๋‹ค. 8์žฅ ์ฐธ์กฐ @ManyToOne=EAGER
@OneToMany=LAZY
cascade ์˜์†์„ฑ ์ „์ด์„ ์‚ฌ์šฉํ•œ๋‹ค. 8์žฅ ์ฐธ์กฐ
targetEntity ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ์˜ ํƒ€์ž… ์ •๋ณด๋ฅผ ์„ค์ • - ์ œ๋„ˆ๋ฆญ์œผ๋กœ ํƒ€์ž… ์ •๋ณด ํ™•์ธ ๊ฐ€๋Šฅ (๊ฑฐ์˜ ์‚ฌ์šฉ X)

5.2 ์—ฐ๊ด€๊ด€๊ณ„ ์‚ฌ์šฉ

5.2.1. ์ €์žฅ

//ํŒ€1 ์ €์žฅ
Team team1 = new Team("team1", "ํŒ€1");
em.persist(team1);

//ํšŒ์›1 ์ €์žฅ
Member member1 = new Member("member1", "ํšŒ์›1");
member1.setTeam(team);
em.persist(member1);

//ํšŒ์›2 ์ €์žฅ
Member member2 = new Member("member2", "ํšŒ์›2");
member2.setTeam(team);
em.persist(member2);

! JPA์—์„œ ์—”ํ‹ฐํ‹ฐ ์ €์žฅ์‹œ ์—ฐ๊ด€๋œ ๋ชจ๋“  ์—”ํ‹ฐํ‹ฐ๋Š” ์˜์† ์ƒํƒœ์—ฌ์•ผ ํ•œ๋‹ค.

member2.setTeam(team); // ํšŒ์› -> ํŒ€ ์ฐธ์กฐ
em.persist(member2); // ์ €์žฅ

5.2.2. ์กฐํšŒ

  1. ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ (๊ฐ์ฒด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•œ ์กฐํšŒ)

    Member member = em.find(Member.class, "member1");
    Team team = member.getTeam(); //๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰
  2. ๊ฐ์ฒด์ง€ํ–ฅ ์ฟผ๋ฆฌ์‚ฌ์šฉ JPQL

    10์žฅ์—์„œ ์•Œ์•„๋ณด์ž..

5.2.3. ์ˆ˜์ •

//์ƒˆ๋กœ์šด ํŒ€2
Team team2 = new Team("team2", "ํŒ€2");
em.persist(team2);

//ํšŒ์›1์— ์ƒˆ๋กœ์šด ํŒ€2 ์„ค์ •
Member member1 = em.find(Member.class, "member1");
member1.setTeam(team2);
  • 3์žฅ์ฐธ์กฐ) ์ˆ˜์ •์€ em.update์™€ ๊ฐ™์€ ๋ฉ”์†Œ๋“œ๊ฐ€ ์—†๋‹ค.
  • ๋‹จ์ˆœํžˆ ์—”ํ‹ฐํ‹ฐ์˜ ๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด ํ”Œ๋Ÿฌ์‹œ์—์„œ ๋ณ€๊ฒฝ๊ฐ์ง€ ๊ธฐ๋Šฅ์ด ๋™์ž‘ํ•˜์—ฌ ๋ณ€๊ฒฝ์‚ฌํ•ญ์„ ์ž๋™์œผ๋กœ DB์— ๋ฐ˜์˜ํ•œ๋‹ค.

5.2.4. ์—ฐ๊ด€๊ด€๊ณ„ ์ œ๊ฑฐ

Member member1 = em.find(Member.class, "member1");
member1.setTeam(null); //์—ฐ๊ด€๊ด€๊ณ„ ์ œ๊ฑฐ

5.2.5. ์—ฐ๊ด€๊ด€๊ณ„ ์‚ญ์ œ

member1.setTeam(null); //ํšŒ์›1 ์—ฐ๊ด€๊ด€๊ณ„ ์ œ๊ฑฐ
member2.setTeam(null); //ํšŒ์›2 ์—ฐ๊ด€๊ด€๊ณ„ ์ œ๊ฑฐ
em.remove(team); //ํŒ€ ์‚ญ์ œ
  • ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์‚ญ์ œํ•˜๋ ค๋ฉด ๊ธฐ์กด์— ์žˆ๋˜ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋จผ์ € ์ œ๊ฑฐํ•˜๊ณ  ์‚ญ์ œํ•ด์•ผํ•œ๋‹ค.
  • ์ง€ํ‚ค์ง€ ์•Š์œผ๋ฉด ์™ธ๋ž˜ํ‚ค ์ œ์•ฝ์กฐ๊ฑด์œผ๋กœ ์ธํ•ด ์˜ค๋ฅ˜ ๋ฐœ์ƒ

5.3 ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„

Untitled

์—ฌ๋Ÿฌ๊ฑด๊ณผ ๊ด€๊ณ„๋ฅผ ๋งบ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปฌ๋ ‰์…˜ ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

Untitled

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ์–‘๋ฐฉํ–ฅ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค. ๋”ฐ๋ผ์„œ ์ถ”๊ฐ€ํ•ด์•ผํ•  ๋‚ด์šฉ์ด ์—†์Œ.

5.3.1. ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘

@Entity
public class Team {
  //์ถ”๊ฐ€๋˜๋Š” ๋ถ€๋ถ„
  @OneToMany(mappedBy = "team")
  private List<Membmer> members = new ArrayList<>();
}

ํŒ€๊ณผ ํšŒ์›์ด ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์ด๊ธฐ ๋•Œ๋ฌธ์— Listํƒ€์ž…์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

@OneToMany ๋งคํ•‘์ •๋ณด ์ถ”๊ฐ€

@MappedBy ๋Š” ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์‹œ ์‚ฌ์šฉ. 5.4์ฑ•ํ„ฐ์—์„œ ๋‚˜์˜ฌ ์˜ˆ์ •

5.3.2 ์ผ๋Œ€๋‹ค ์ปฌ๋ ‰์…˜ ์กฐํšŒ

Team team = em.find(Team.class, "team1");
List<Member> members = team.getMembers(); // ํŒ€ -> ํšŒ์›
																					// ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰

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

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

  • ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค ํ•˜๋‚˜๋กœ ๋‘ ํ…Œ์ด๋ธ”์˜ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.
  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ๋งคํ•‘ํ•˜๋ฉด ์ฐธ์กฐ๋ฅผ ํ•˜๋‚˜๋งŒ ์‚ฌ์šฉํ•œ๋‹ค.
  • ํ•˜์ง€๋งŒ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋งคํ•‘ํ•˜๊ฒŒ ๋˜๋ฉด ์„œ๋กœ๋ฅผ ์ฐธ์กฐํ•ด์•ผํ•œ๋‹ค.
  • = ๊ด€๋ฆฌํฌ์ธํŠธ๊ฐ€ 2๊ณณ์œผ๋กœ ๋Š˜์–ด๋‚œ๋‹ค.
  • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋กœ ์„ค์ •ํ•˜๋ฉด ์ฐธ์กฐ๋Š” ๋‘˜, ์™ธ๋ž˜ํ‚ค๋Š” 1๊ฐœ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ๊ตฌ ๊ฐ์ฒด ์—ฐ๊ด€๊ด€๊ณ„ ์ค‘ ํ•˜๋‚˜๋ฅผ ์ •ํ•ด์„œ ํ…Œ์ด๋ธ”์˜ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค.

5.4.1. ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์˜ ๊ทœ์น™ : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ๋งŒ์ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ด€๊ด€๊ณ„์™€ ๋งคํ•‘๋˜๊ณ , ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ด€๋ฆฌ (๋“ฑ๋ก, ์ˆ˜์ •, ์‚ญ์ œ) ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋‹Œ ์ชฝ์€ ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.

@Mapped ์†์„ฑ

  • ์ฃผ์ธ์€ MappedBy์†์„ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค
  • ์ฃผ์ธ์ด ์•„๋‹ˆ๋ฉด ์†์„ฑ์˜ ๊ฐ’์˜ ์ฃผ์ธ์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

5.4.2. ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์€ ์™ธ๋ž˜ํ‚ค๊ฐ€ ์žˆ๋Š” ๊ณณ

Untitled

  • ํšŒ์› ํ…Œ์ด๋ธ”์ด ์™ธ๋ž˜ ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฏ€๋กœ Member.team์ด ์ฃผ์ธ
  • ์ฃผ์ธ์ด ์•„๋‹Œ Team.members์—๋Š” mappedBy=โ€œteamโ€ ์†์„ฑ์„ ์‚ฌ์šฉํ•ด์„œ ์ฃผ์ธ์ด ์•„๋‹˜์„ ์„ค์ •
  @OneToMany(mappedBy = "team")
  private List<Membmer> members = new ArrayList<>();

mappedBy ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋œ team์€ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ธ Member.team

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”์˜ ๋‹ค๋Œ€์ผ, ์ผ๋Œ€๋‹ค ๊ด€๊ณ„์—์„œ๋Š” ํ•ญ์ƒ ๋‹ค ์ชฝ์ด ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ฐ€์ง. ๋‹ค ์ชฝ์ธ @ManyToOne์€ ํ•ญ์ƒ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๋œ๋‹ค.

๋”ฐ๋ผ์„œ @ManyToOne์—๋Š” mappedBy์†์„ฑ์ด ์—†๋‹ค.

5.5 ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ์ €์žฅ

team.getMembers().add(member1); //๋ฌด์‹œ : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ์•„๋‹˜
team.getMembers().add(member2); //๋ฌด์‹œ : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ์•„๋‹˜
member1.setTeam(team1) //์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ • : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ
member2.setTeam(team1); //์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ • : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ

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

์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •์—์„œ ๊ฐ€์žฅ ํ”ํ•œ ์‹ค์ˆ˜๋Š” ์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ์—๊ฒŒ ๊ฐ’์„ ์ž…๋ ฅํ•˜์ง€ ์•Š๊ณ , ์•„๋‹Œ ๊ณณ์—๋งŒ ๊ฐ’์„ ์ž…๋ ฅํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

team.getMembers().add(member1); //๋ฌด์‹œ : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ์•„๋‹˜
team.getMembers().add(member2); //๋ฌด์‹œ : ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ์•„๋‹˜

em.persist(team)

์—ฐ๊ด€๊ด€๊ณ„ ์ฃผ์ธ์ด ์•„๋‹Œ Team์—๋งŒ ๊ฐ’์„ ์ž…๋ ฅํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ DB์— ์ €์žฅ๋˜์ง€ ์•Š์Œ.

5.6.1. ์ˆœ์ˆ˜ํ•œ ๊ฐ์ฒด๊นŒ์ง€ ๊ณ ๋ คํ•œ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„

๊ฐ์ฒด ๊ด€์ ์—์„œ ์–‘์ชฝ ๋ฐฉํ–ฅ์— ๋ชจ๋‘ ๊ฐ’์„ ์ž…๋ ฅํ•ด์ฃผ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์•ˆ์ „ํ•˜๋‹ค.

member1.setTeam(team);
team.getMembers().add(member1); 

em.persist(member1)

5.6.2. ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์†Œ๋“œ

public class Member {
    private Team team;

    public void setTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
}

//์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •
member1.setTeam(team1);

5.6.3. ์—ฐ๊ด€๊ด€๊ณ„ ํŽธ์˜ ๋ฉ”์†Œ๋“œ ์ž‘์„ฑ์‹œ ์ฃผ์˜์‚ฌํ•ญ

์‚ฌ์‹ค ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋‹ค.

๊ธฐ์กด ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์‚ญ์ œํ•˜์ง€ ์•Š์•˜๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

public class Member {
    public void setTeam(Team team) {
        //๊ธฐ์กด ํŒ€๊ณผ ๊ด€๊ณ„๋ฅผ ์ œ๊ฑฐ
        if (this.team != null) {
            this.team.getMembers().remove(this);
        }
        this.team = team;
        team.getMembers().add(this);
    }
}

5.7 ์ •๋ฆฌ

์–‘๋ฐฉํ–ฅ์˜ ์žฅ์ ์€ ๋ฐ˜๋Œ€๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋œ ๊ฒƒ ๋ฟ์ด๋‹ค.

์ฃผ์ธ์˜ ๋ฐ˜๋Œ€ํŽธ์€ MappedBy๋กœ ์ฃผ์ธ์„ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค.

  • ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๋งŒ์œผ๋กœ ํ…Œ์ด๋ธ”๊ณผ ๊ฐ์ฒด์˜ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘์€ ์ด๋ฏธ ์™„๋ฃŒ๋˜์—ˆ๋‹ค.
  • ๋‹จ๋ฐฉํ–ฅ์„ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋งŒ๋“ค๋ฉด ๋ฐ˜๋Œ€๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋œ๋‹ค.
  • ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งคํ•‘ํ•˜๋ ค๋ฉด ๊ฐ์ฒด์—์„œ ์–‘์ชฝ ๋ฐฉํ–ฅ์„ ๋ชจ๋‘ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์€ ์™ธ๋ž˜ ํ‚ค์˜ ์œ„์น˜์™€ ๊ด€๋ จํ•ด์„œ ์ •ํ•ด์•ผํ•˜์ง€ ๋น„์ฆˆ๋‹ˆ์Šค์˜ ์ค‘์š”๋„๋กœ ์ ‘๊ทผํ•˜๋ฉด ์•ˆ๋œ๋‹ค.


**์–‘๋ฐฉํ–ฅ ๋งคํ•‘์‹œ์—๋Š” ๋ฌดํ•œ ๋ฃจํ”„์— ์กฐ์‹ฌํ•ด์•ผํ•œ๋‹ค.**

Member.toString()์—์„œ getTeam()์„ ํ˜ธ์ถœํ•˜๊ณ  Team.toString()์—์„œ getMember()์„ ํ˜ธ์ถœํ•˜๋ฉด ๋Š์ž„์—†๋Š” ์žฌ๊ท€ํ•จ์ˆ˜๊ฐ€ ๋˜์–ด ๋ฌดํ•œ ๋ฃจํ”„์— ๋น ์งˆ ์ˆ˜ ์žˆ๋‹ค.


๋‹ค ์ชฝ์ด ์•„๋‹Œ ๋‹จ ์ชฝ์„ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์œผ๋กœ ํ•  ์ˆ˜๋„ ์žˆ๊ธด ํ•˜๋‹ค. ๋‹ค๋งŒ ์„ฑ๋Šฅ์ด๋‚˜ ๊ด€๋ฆฌ ์ธก๋ฉด์—์„œ ๊ถŒ์žฅํ•˜์ง€ ์•Š๋Š”๋‹ค. 6์žฅ ์ฐธ๊ณ