JiwonDev

JPA #5 ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ ์„ค๊ณ„์˜ ๋ฌธ์ œ์ , ์—ฐ๊ด€ ๊ด€๊ณ„ ๋งคํ•‘

by JiwonDev

๐Ÿ“Œ ํ…Œ์ด๋ธ”๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๊ฐ์ฒด๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•

๊ธฐ์กด์˜ JDBC๋ฅผ ์ด์šฉํ•˜๋˜ ๋ฐฉ์‹์€ ๊ฐ์ฒด ์„ค๊ณ„๋ฅผ ํ…Œ์ด๋ธ”์— ๋งž์ถฐ์•ผํ•œ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๋‹ค. ๊ฐ์ฒด๊ฐ€ ์•„๋‹Œ ๋ฐ์ดํ„ฐ ์ค‘์‹ฌ์˜ ์„ค๊ณ„.

public class Order{
    private Long id;
    private Long memberId; // ์—ฐ๊ด€ ๊ด€๊ณ„๋Š” ๋‹จ์ˆœํžˆ id๋กœ ํ‘œํ˜„
    
    // ... ์ดํ•˜ ์ƒ๋žต ... //
}
private Member member // ์ด๋ ‡๊ฒŒ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์„ ์ˆ˜ ์—†๋‹ค.
member.getAddress().getCity() // ์ด๋Ÿฐ๊ฑด ๋‹น์—ฐํžˆ ๋ถˆ๊ฐ€๋Šฅ

๊ฐ์ฒด ๊ทธ๋ž˜ํ”„ ํƒ์ƒ‰์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ณ , ๋‹จ์ˆœํ•œ id ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๋ฟ ๊ฐ์ฒด๋ผ๋ฆฌ ์–ด๋– ํ•œ ๊ด€๊ณ„๋„ ์—ฐ๊ฒฐ๋˜์–ด์žˆ์ง€ ์•Š๋‹ค.

 

DB์—๋Š” ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด์žˆ์ง€๋งŒ, ๊ฐ์ฒด์—๋Š” ๋‹จ์ˆœ id ๊ฐ’๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๋ฟ ์–ด๋– ํ•œ ์•ˆ์ „์žฅ์น˜๋„ ์—†๋‹ค.

 

JPA๋กœ ์ฝ”๋“œ๋ฅผ ์˜ฎ๊ธฐ๋ฉด, ์•„๋ž˜์™€ ๊ฐ™์ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @Column(name = "TEAM_ID")
    private Long teamId; //๋งŒ์•ฝ Team ๊ฐ์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด?
…
}
@Entity
public class Team {

    @Id
    @GeneratedValue
    private Long id;
    private String name; 
…
}

 

์•„๋ฌด๋ฆฌ JPA๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋“ค, ์ด๋ ‡๊ฒŒ ์ง€์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ์‹๋ณ„์ž(id)๋ฅผ ์ด์šฉํ•ด์„œ ํ•œ๋ฒˆ ๋” ์กฐํšŒํ•ด์•ผํ•œ๋‹ค.

์ด๋ ‡๊ฒŒ ๊ฐ์ฒด์ง€ํ–ฅ์„ ํฌ๊ธฐํ•˜๊ณ  ํ…Œ์ด๋ธ”์— ๋งž์ถฐ ๋ชจ๋ธ๋งํ•˜๋Š”๊ฒŒ ๋งž๋Š” ๋ฐฉ๋ฒ•์ผ๊นŒ?

//ํšŒ์› ์ €์žฅ
 Member member = new Member();
 member.setName("member1");
 member.setTeamId(team.getId()); // ๊ทธ๋ƒฅ id๊ฐ’์„ ์ €์žฅ
 em.persist(member);

//์กฐํšŒ
 Member findMember = em.find(Member.class, member.getId()); 

//์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ์—†์Œ. ๊ทธ๋ƒฅ id ๊ฐ’์œผ๋กœ ์กฐํšŒํ•˜๋Š” ๊ฒƒ์ผ ๋ฟ์ž„
 Team findTeam = em.find(Team.class, team.getId());
  • DB ํ…Œ์ด๋ธ”์€ ์™ธ๋ž˜ ํ‚ค์™€ ์กฐ์ธ์„ ์ด์šฉํ•ด์„œ ์—ฐ๊ด€๋œ ํ…Œ์ด๋ธ”์„ ์ฐพ๋Š”๋‹ค.
  • ๊ฐ์ฒด์—์„œ๋Š” ์™ธ๋ž˜ ํ‚ค๋ผ๋Š” ๊ฐœ๋…์ด ์—†๋‹ค. ์ฐธ์กฐ๋ฅผ ํ†ตํ•ด์„œ ์—ฐ๊ด€๋œ ๊ฐ์ฒด๋ฅผ ์ฐพ๋Š”๋‹ค.

๊ฐ์ฒด์ง€ํ–ฅ์€ ์–ด๋– ํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ ๊ฐ์ฒด๋“ค์ด ํ˜‘๋ ฅํ•˜๊ณ  ์ฑ…์ž„์„ ๋‚˜๋ˆ  ํ•ด๊ฒฐํ•œ๋‹ค.

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

 

 

 

๐Ÿ“Œ ๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘

@ManyToOne์œผ๋กœ ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘์„ ์„ค์ •ํ•˜๊ณ 

@JoinColumn์œผ๋กœ ์กฐ์ธํ•  ์นผ๋Ÿผ์„ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์• ๋…ธํ…Œ์ด์…˜ ์œผ๋กœ ๋งคํ•‘์ด ๋๋‚œ๋‹ค.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
	
}

 

์ด๋ ‡๊ฒŒํ•˜๋ฉด ๋†€๋ž๊ฒŒ๋„ ์‚ฌ์šฉํ•  ๋•Œ ๊ทธ๋ƒฅ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋“ฏ์ด ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

์‹ฌ์ง€์–ด ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ ๋‘˜ ๋‹ค ์ƒ์„ฑํ•˜๋ฉด 1์ฐจ ์บ์‹œ๋ฅผ ์ด์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์ปค๋ฐ‹ ์ „์—๋Š” DB ์ฟผ๋ฆฌ๋ฅผ ๋‚ ๋ฆฌ์ง€๋„ ์•Š๋Š”๋‹ค.

Member์™€ Team์€ [ N:1, Many โžก One ] ๊ด€๊ณ„์ด๋‹ค.

 //ํŒ€ ์ €์žฅ
 Team team = new Team();
 em.persist(team);
 
 //ํšŒ์› ์ €์žฅ
 Member member = new Member();
 member.setTeam(team); //๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •, ์ฐธ์กฐ ์ €์žฅ
 em.persist(member)
//์กฐํšŒ
Member findMember = em.find(Member.class, member.getId());

//์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—ฐ๊ด€๊ด€๊ณ„ ์กฐํšŒ
Team findTeam = findMember.getTeam();

๋งŒ์•ฝ ๋‹ค๋ฅธ Team์œผ๋กœ ๊ต์ฒดํ•  ๋•Œ๋„, ๊ทธ๋ƒฅ Member.setTeam(~)์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด DB ์™ธ๋ž˜ํ‚ค ๊ฐ’์ด ์—…๋ฐ์ดํŠธ๋œ๋‹ค.

 

 

๐Ÿ“Œ ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘

์ž˜ ์ƒ๊ฐํ•ด๋ณด๋ฉด, DB ํ…Œ์ด๋ธ”์—๋Š” '๋‹จ๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„'๋ผ๋Š” ๊ฐœ๋… ์ž์ฒด๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค.

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

 

๊ฐ์ฒด๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. ์ฐธ์กฐ ๊ฐ’์ด ์—†์œผ๋ฉด ์ ‘๊ทผ์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ทธ๋ž˜์„œ ๋‹จ๋ฐฉํ–ฅ ์ฐธ์กฐ 2๊ฐœ๋ฅผ ๋งŒ๋“ค์–ด ์–‘๋ฐฉํ–ฅ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค.

๋‹ค๋งŒ ์™ธ๋ž˜ํ‚ค๋กœ ๊ด€๊ณ„๊ฐ€ ๋งบ์–ด์กŒ๋‹ค๋ฉด ๋‹จ๋ฐฉํ–ฅ, ์–‘๋ฐฉํ–ฅ์˜ ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด DB ํ…Œ์ด๋ธ”์€ ๋˜‘๊ฐ™๋‹ค๋Š” ๊ฑธ ์ธ์ง€ํ•˜์ž.

DB๋Š” ์™ธ๋ž˜ํ‚ค๊ฐ€ ์žˆ์œผ๋ฉด ์–‘์ชฝ์—์„œ ์ฐธ์กฐ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ฐ์ฒด๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค.

์šฐ์„  Member์—์„œ ๋‹ค๋ฅธ์ ์€ ์—†๋‹ค. ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๊ณผ ๋™์ผํ•˜๋‹ค.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
	
}

Team์—์„œ๋Š” @OneToMany๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ์—ฌ๋Ÿฌ Member๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ปฌ๋ ‰์…˜์„ ์ด์šฉํ•ด์•ผํ•œ๋‹ค.

* ๋‹จ, mappedBy๋ฅผ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ  ์žˆ์ง€ ์•Š์œผ๋ฉด DB์— ์ œ๋Œ€๋กœ ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋ฐ, ์ด๋Š” ์•„๋ž˜์—์„œ ์•Œ์•„๋ณด์ž.

@Entity
public class Team {

    @Id
    @GeneratedValue
    private Long id;
    
    @OneToMany(mappedBy = "team") // Member.team ์ด ์ฃผ์ธ์ž„.
    List<Member> members = new ArrayList<Member>();

}

 

์ด์ œ Team์—์„œ Member๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

//์กฐํšŒ
 Team findTeam = em.find(Team.class, team.getId()); 
 int memberSize = findTeam.getMembers().size(); //์—ญ๋ฐฉํ–ฅ ์กฐํšŒ

 

 

โœ” ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ๊ณผ (mappedBy="~")

mappedBy๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„์˜ ์ฃผ์ธ(=์™ธ๋ž˜ํ‚ค๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์ชฝ)์„ ์„ค์ •ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

@OneToOne, @OneToMany, @ManyToMany ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ด๋ฉฐ, mappedBy๊ฐ€ ์—†๋‹ค๋ฉด JPA์—์„œ๋Š” ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋กœ ์„ค์ •ํ•˜์ง€ ์•Š์€ ์ƒํƒœ๋กœ ํ…Œ์ด๋ธ”์„ ๋งคํ•‘ํ•œ๋‹ค.

// List<players>๊ฐ€ ๊ด€๊ณ„์˜ ์ฃผ์ธ์ž„์„ ๋‚˜ํƒ€๋‚ด๊ธฐ์œ„ํ•ด, mappedBy = "team" ์„ ์ ์–ด์ค€๋‹ค.
@OneToMany(mappedBy = "team") // Member.team
private List<Player> players = new ArrayList<Player>();

 

๊ทธ๋Ÿฐ๋ฐ @OneToMany๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ, ๋ฐ˜๋“œ์‹œ mappedBy๋กœ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์„ ์ง€์ •ํ•ด์ค˜์•ผํ•œ๋‹ค. ์™œ ๊ทธ๋Ÿด๊นŒ?

@OneToMany // ?? ๊ทธ๋ƒฅ ์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•ด๋„ ๋ณ„ ๋ฌธ์ œ์—†๋Š”๊ฑฐ ์•„๋‹Œ๊ฐ€?
List<Member> members = new ArrayList<Member>();

 

๊ทธ ์ด์œ ๋Š” ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋ฅผ 2๊ฐœ๋ฅผ ๊ฐ€์ง€์ง€๋งŒ, DB๋Š” ์™ธ๋ž˜ํ‚ค 1๊ฐœ๋กœ ์–‘๋ฐฉํ–ฅ ์ฐธ์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • DB์—์„œ๋Š” 1๊ฐœ์˜ ์™ธ๋ž˜ํ‚ค๋กœ ํ…Œ์ด๋ธ”์„ ์„œ๋กœ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ์ฒด์—์„œ๋Š” ๋‹จ๋ฐฉํ–ฅ ์ฐธ์กฐ๊ฐ€ 2๊ฐœ๊ฐ€ ๋งŒ๋“ค์–ด์ง„๋‹ค. ์ฆ‰ ์™ธ๋ž˜ํ‚ค ์—ญํ• ์„ ํ•˜๋Š” ์ฐธ์กฐ๊ฐ€ 2๊ฐœ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

DB์— ํ•œ ๊ด€๊ณ„์— ์™ธ๋ž˜ํ‚ค๋ฅผ 2๊ฐœ๋ฅผ ๋„ฃ๋Š” ๊ธฐ๋Šฅ์€ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•  ์ด์œ ๋„ ์—†๊ณ 

๋ณ„๋กœ ์•ˆ์ค‘์š”ํ•ด๋ณด์—ฌ๋„, ์ด๋Š” ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ์™ธ๋ž˜ํ‚ค๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š”๊ฑด 'ํ•œ ๊ฐ์ฒด๋งŒ' ๊ฐ€๋Šฅํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

  • DB๋Š” ์™ธ๋ž˜ํ‚ค๊ฐ€ 1๊ฐœ์ง€๋งŒ, ๊ฐ์ฒด์—๋Š” ์–‘์ชฝ ๋‘ ๊ฐ€์ง€ ์ฐธ์กฐ๊ฐ’์ด ์žˆ๋‹ค.
      Member โžก Team ์ฐธ์กฐ๊ฐ’
      Team โžก Member ์ฐธ์กฐ๊ฐ’

  • ๊ทธ๋ƒฅ ๋‘ ๊ฐœ์˜ ์ฐธ์กฐ๊ฐ’ ๋‹ค ๋งคํ•‘ํ•˜๋ฉด ์•ˆ๋˜๋‚˜?
      ๊ทน๋‹จ์ ์œผ๋กœ Member.team์—๋Š” ๊ฐ’์„ ๋„ฃ๊ณ , Team.members์—๋Š” ๊ฐ’์„ ๋„ฃ์ง€ ์•Š๋Š”๋‹ค๋ฉด?
      ๋ฐ˜๋Œ€๋กœ Member.team์€ ๊ฐ’์„ ๋„ฃ์ง€ ์•Š๊ณ , Team.members์—๋งŒ ๊ฐ’์„ ๋„ฃ๋Š”๋‹ค๋ฉด?
      ์•„๋‹ˆ๋ฉด ๋‘˜ ๋‹ค ๋‹ค๋ฅธ ๊ฐ’์„ ๋™์‹œ์— ๋„ฃ๋Š”๋‹ค๋ฉด?
      ๊ฐ™์€ ์ฐธ์กฐ์ธ๋ฐ ์–‘์ชฝ์˜ ๊ฐ’์ด ๋‹ค๋ฅด๋‹ค๋ฉด JPA๋Š” ๋ฌด์—‡์„ ๊ธฐ์ค€์œผ๋กœ ๋ณ€๊ฒฝํ•˜์ง€?

  • ๋”ฐ๋ผ์„œ ๊ทœ์น™์ด ์ƒ๊น€
      ๋‘˜ ์ค‘ ํ•˜๋‚˜๋กœ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค โžก ์—ฐ๊ด€๊ด€๊ณ„(์™ธ๋ž˜ํ‚ค)์˜ ์ฃผ์ธ
      (์ฃผ์ธ์ด Member) Member์— ์žˆ๋Š” team๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ์™ธ๋ž˜ํ‚ค ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•˜๋‚˜.
      (์ฃผ์ธ์ด Team) Team์— ์žˆ๋Š” members๊ฐ’์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ์™ธ๋ž˜ํ‚ค ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•ด์•ผํ•˜๋‚˜.

๊ทธ๋ž˜์„œ JPA์—์„œ๋Š” ์™ธ๋ž˜ํ‚ค๋ฅผ ๋‹ค๋ฃฐ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์„ ์ •ํ•˜๊ณ , ์ฃผ์ธ์ด ์•„๋‹Œ ์ชฝ์€ ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค๊ณ„๋˜์–ด์žˆ๋‹ค.

 

์ฆ‰ ์—ฐ๊ด€๊ด€๊ณ„์˜ โœจ์ฃผ์ธ์ด ์•„๋‹Œ ์ชฝ์—์„œ๋Š”, ์ฐธ์กฐ๊ฐ’์„ ํ†ตํ•ด ๊ฐ’์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค. ์ˆ˜์ •ํ•ด๋„ DB์— ๋ฐ˜์˜๋˜์ง€ ์•Š๋Š”๋‹ค.

๋˜ ์•„๋ฌด ์ƒ๊ฐ์—†์ด ์ฃผ์ธ์„ ์ •ํ•ด๋ฒ„๋ฆฌ๋ฉด ๊ฐ์ฒด์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง€๊ณ , ์ „ํ˜€ ์ƒ๊ด€์—†๋Š” ํ…Œ์ด๋ธ”์— DB ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

 

 

โœ” ๋ˆ„๊ตฌ๋ฅผ ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์œผ๋กœ ์ •ํ•ด์•ผํ•˜๋Š”๊ฐ€?

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

๋น„์ฆˆ๋‹ˆ์Šค๋งˆ๋‹ค Team์ด ์ฃผ์ธ์ด ๋  ์ˆ˜๋„, Member๊ฐ€ ์ฃผ์ธ์ด ๋  ์ˆ˜๋„ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋ณดํ†ต์€ ๋‹ค๋Œ€์ผ ๋ฐฉํ–ฅ์œผ๋กœ, Many๊ฐ€ ์ฃผ์ธ์ด ๋˜๋Š”๊ฒŒ ์ข‹๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ๋Š” ManyToOne ๊ด€๊ณ„์—์„œ Many์ชฝ, Member.team์ด ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด๋‹ค.

๋ฌผ๋ก  Team์„ ์ฃผ์ธ์œผ๋กœ ์ •ํ•  ์ˆ˜ ๋„ ์žˆ๋‹ค. ์™œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ์•ˆ๋ ๊นŒ?

  • ํ•˜๋‚˜์˜ ํŒ€์€ ์—ฌ๋Ÿฌ Member๋ฅผ ๊ฐ€์ง„๋‹ค. ๋งŒ์•ฝ Team์„ ์ˆ˜์ •ํ•˜๊ฒŒ๋˜๋ฉด ๋ชจ๋“  members์—๊ฒŒ DB ์ฟผ๋ฆฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.
  • Member์—์„œ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๊ธฐ๋•Œ๋ฌธ์—, Member๊ฐ€ ์Šค์Šค๋กœ Team์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜๋ฒ„๋ฆฐ๋‹ค.

 

๋ณ„๋กœ ์–ด๋ ต์ง€์•Š์ง€๋งŒ ์‹ค์ œ ์ฝ”๋“œ์—์„œ ์ •๋ง ์ •๋ง ๋งŽ์ด ์‹ค์ˆ˜ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค. JPA๋ฅผ ์ดํ•ดํ•˜๊ณ  ์žˆ์ง€์•Š์œผ๋ฉด ์ฐพ๊ธฐ๋„ ์–ด๋ ต๋‹ค.

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ DB ์™ธ๋ž˜ํ‚ค์—๋Š” null์ด ๋“ค์–ด๊ฐ€์žˆ๋‹ค.

// ํ•ด๋‹น JPA์ฝ”๋“œ๋Š” Member์™€ Team์ด ์—ฐ๊ฒฐ๋˜์ง€ ์•Š๋Š”๋‹ค. DB ์™ธ๋ž˜ํ‚ค์—๋Š” null์ด ๋“ค์–ด๊ฐ€์žˆ๋‹ค.
// ๋ฌด์—‡์ด ๋ฌธ์ œ์ธ์ง€ ๋ณด์ด๋Š”๊ฐ€?
 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)์—์„œ ๋“ฑ๋กํ•ด์ฃผ์–ด์•ผ ๋œ๋‹ค.

member.setTeam(team);  //์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’ ์„ค์ •

 

์ฃผ์ธ์ชฝ์ธ member์—์„œ ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๋งŒ ํ•ด์ฃผ๋”๋ผ๋„, ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

// Team์—๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„ ์„ค์ •์„ ํ•˜์ง€ ์•Š์•˜์Œ.
 Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
// Member์—์„œ๋Š” team๊ณผ ๊ด€๊ณ„ ์„ค์ •์„ ํ•˜์˜€์Œ.
 Member member = new Member();
 member.setName("member1");
 member.setTeam(team);
 em.persist(member)
 
// ํ™•์‹คํ•˜๊ฒŒ DB์—์„œ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐ
  em.flush();
  em.clear();
// Team์—์„œ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์ง€์ •ํ•˜์ง€ ์•Š์•˜์Œ์—๋„, ์•„๋ž˜์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•ด๋„ member๊ฐ€ ์ •์ƒ ์ฐธ์กฐ๋จ.
Team findTeam = em.find(Team.class, team.getId());
findTeam.getMembers();

JPA ๋™์ž‘์‹œ Team ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ฐธ๊ณ ํ•ด์„œ, ์ฟผ๋ฆฌ๊ฐ€ ๋‚˜๊ฐˆ ๋•Œ ์—ฐ๊ด€๋œ member๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ค๊ธฐ ๋•Œ๋ฌธ์ด ๊ทธ๋ ‡๋‹ค.

 

 

โœ” ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„๋Š” ์–‘์ชฝ์—์„œ ๋งบ์–ด์ฃผ๋Š”๊ฒŒ ์ข‹๋‹ค.

์œ„์—์„œ ๋งํ•œ๋Œ€๋กœ ์ฃผ์ธ์ชฝ (Member)์—์„œ๋งŒ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ์–ด๋„, ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๊ธดํ•˜๋‹ค.

ํ•˜์ง€๋งŒ ์‹ค์ œ ์‚ฌ์šฉ์€ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ด€๊ณ„๋ฅผ ๋ถ™์—ฌ์„œ ์–‘์ชฝ์—์„œ ๋‹ค ๋งบ์–ด์ฃผ๋Š”๊ฒŒ ๋งž๋‹ค.

member.setTeam(team);
team.getMembers().add(member); // ์—ฅ? ์ด๊ฑด DB์— ๋ฐ˜์˜์ด ์•ˆ๋œ๋‹ค๋ฉด์„œ์š”? ๊ท€์ฐฎ๊ฒŒ ์™œ ๊ตณ์ด

๋” ํ™•์‹คํ•œ ๋ฐฉ๋ฒ•์€, ๊ทธ๋ƒฅ ์›์ž์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ Member์— ๊ด€๊ณ„๋ฅผ ์„ค์ •ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฐ”๋กœ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค.

Team์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ค˜๋„ ์ƒ๊ด€์€ ์—†๋‹ค. ๋‹ค๋งŒ ์–‘์ชฝ ๋‹ค ํ•˜๋ฉด ๋ฌดํ•œ๋ฃจํ”„ & ๋ฒ„๊ทธ์˜ ์œ„ํ—˜์ด ์žˆ์œผ๋ฏ€๋กœ ํ•˜๋‚˜๋งŒ ํ•˜์ž.

@Entity
public class Member {

    @Id
    @GeneratedValue
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
	
    public void setTeam(Team team){
    	this.team=team;
        team.getMembers().add(this); // ๋ฐ”๋กœ ์–‘์ชฝ ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ์„ค์ •.
    }
}

 

๊ตณ์ด ์ด๋ ‡๊ฒŒ ํ•˜๋Š”๊ฑด Java๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ๊ฐ์ฒด์ง€ํ–ฅ์ ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฌ์›Œ์„œ ๊ทธ๋Ÿฐ ๊ฒƒ๋„์žˆ์ง€๋งŒ, ๋‚ด๋ถ€๋™์ž‘์—๋„ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

  • ํ•œ ํŠธ๋žœ์žญ์…˜ ๋‚ด์—์„œ ์ œ๋Œ€๋กœ ์กฐํšŒ๊ฐ€ ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

DB์— ๋ฐ˜์˜์ด ๋˜๋Š” ์‹œ์ ์—๋Š” ์ƒ๊ด€์—†์ง€๋งŒ, ์•„๋ž˜์™€ ๊ฐ™์ด ํ•œ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ์‚ฌ์šฉ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค. ๋‹น์—ฐํžˆ ์ปค๋ฐ‹ ๋˜๊ธฐ์ „ ์ˆœ์ˆ˜ํ•œ Team ๊ฐ์ฒด์—๋Š” ์•„์ง ๊ฐ’์ด ๋“ค์–ด๊ฐ€์ง€ ์•Š์•˜์œผ๋‹ˆ๊นŒ.

// Team์—๋Š” ์—ฐ๊ด€ ๊ด€๊ณ„ ์„ค์ •์„ ํ•˜์ง€ ์•Š์•˜์Œ.
 Team team = new Team();
 team.setName("TeamA");
 em.persist(team);
 
// Member์—์„œ๋Š” team๊ณผ ๊ด€๊ณ„ ์„ค์ •์„ ํ•˜์˜€์Œ.
 Member member = new Member();
 member.setName("member1");
 member.setTeam(team);
 em.persist(member)

// ์กฐํšŒํ•˜๋ฉด null์ด ๋‚˜์˜จ๋‹ค.
// ๋‹น์—ฐํ•œ๊ฑฐ๋‹ค. ์ปค๋ฐ‹๋˜์ง€ ์•Š์•˜์œผ๋ฉด ์ˆœ์ˆ˜ํ•œ ์ž๋ฐ” ๊ฐ์ฒด๋‹ˆ๊นŒ. ๊ฐ’์„ ๋„ฃ์€์ ์ด ์—†์ž–์•„?
 Team findTeam = em.find(Team.class, team.getId());
 findTeam.getMembers();

 

Team์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ค˜๋„ ์ƒ๊ด€์€ ์—†๋‹ค. ๋‹ค๋งŒ ์–‘์ชฝ ๋‹ค ํ•˜๋ฉด ๋ฌดํ•œ๋ฃจํ”„ & ๋ฒ„๊ทธ์˜ ์œ„ํ—˜์ด ์žˆ์œผ๋ฏ€๋กœ ํ•˜๋‚˜๋งŒ ํ•˜์ž.

์–‘์ชฝ์œผ๋กœ ์„ค์ •ํ•˜์ง€ ๋ง๋ผ๋Š” ์ด์œ ์™€ ๊ฐ™๊ฒŒ toString(), lombok, JSON ๋“ฑ์„ ์‚ฌ์šฉํ•  ๋•Œ ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์„ ์ž˜๋ชป์‚ฌ์šฉํ•˜๋ฉด ๋ฌดํ•œ๋ฃจํ”„๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์กฐ์‹ฌํ•ด์„œ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜์ž.

 

์ œ์ผ ์ข‹์€ ๋ฐฉ๋ฒ•์€ lombok์—์„œ team.toString() ๊ฐ™์€ ๊ฑธ ์•„์˜ˆ ์“ฐ์ง€๋ง๊ณ , ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ์—์„œ Entity ๋Œ€์‹  DTO๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ด๊ฒƒ๋งŒ ์ฃผ์˜ํ•ด๋„ ํฐ ๋ฌธ์ œ๊ฐ€ ์•ˆ์ƒ๊ธด๋‹ค.

// ์ด๋ ‡๊ฒŒ ์–‘์ชฝ์œผ๋กœ ๋ฌดํ•œ ์ฐธ์กฐ๋ฅผ ํ•˜๋ฉด์„œ ์•ฑ์ด ์ฃฝ์–ด๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.
public toString(){
	return "member=" + name + "team" + team; // team.toString() ํ˜ธ์ถœ
}

public toString(){
	return "team members" + members; // member.toString() ํ˜ธ์ถœ
}

 

๐Ÿ“Œ  ๊ฒฐ๋ก : ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์„ ๋˜๋„๋ก์ด๋ฉด ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”.

DB ํ…Œ์ด๋ธ”์„ ์ฒ˜์Œ ์„ค๊ณ„ํ•  ๋•Œ, ๋‹จ๋ฐฉํ–ฅ ๋งคํ•‘๋งŒ์œผ๋กœ ์„ค๊ณ„๋ฅผ ์™„๋ฃŒํ•˜๋Š” ๊ฒŒ ์ข‹๋‹ค.

์–ด์ฐจํ”ผ ManyToOne ๊ด€๊ณ„๊ฐ€ ๋‚˜์˜ค๋ฉด ์กฐํšŒํ•˜๋Š” ๋ฐฉํ–ฅ์„ ์‰ฝ๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

์œ„์—์„œ ๋ฐฐ์› ๊ฒ ์ง€๋งŒ ๊ฐ์ฒด์ž…์žฅ์—์„œ ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์„ ์‚ฌ์šฉํ•˜๋Š”๊ฑด ์ •๋ง ๋จธ๋ฆฌ ์•„ํ”ˆ ์ผ์ด๋‹ค. ์ตœ์ดˆ ์„ค๊ณ„์—๋Š” ๋‹จ๋ฐฉํ–ฅ๋งŒ ์‚ฌ์šฉํ•˜์ž.

 

๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ ์–‘๋ฐฉํ–ฅ ๋งคํ•‘์ด ๊ผญ ํ•„์š”ํ•  ๋•Œ (ex JPQL์„ ์ด์šฉํ•ด์„œ ์—ญ๋ฐฉํ–ฅ์œผ๋กœ ํƒ์ƒ‰ํ•  ๋•Œ) ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ์ข‹๋‹ค.

์–ด์ฐจํ”ผ ์–‘๋ฐฉํ–ฅ, ๋‹จ๋ฐฉํ–ฅ์€ ๊ฐ์ฒด์—๋งŒ ์žˆ๋Š” ๊ฐœ๋…์ด๊ณ  DB ํ…Œ์ด๋ธ”์—๋Š” ์•„๋ฌด๋Ÿฐ ์˜ํ–ฅ์ด ์—†์–ด์„œ ํ•„์š”ํ•  ๋•Œ ์‰ฝ๊ฒŒ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ