Server๐Ÿงค/JPA

[JPA] ์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„

yujindonut 2023. 2. 3. 14:44
728x90

 

๊ฐœ๋ฐœ์„ ํ•˜๋‹ค๋ณด๋ฉด Team์— ์†ํ•œ Member๋“ค์„ ๊ฐ€์ ธ์™€์•ผํ• ๋•Œ๊ฐ€ ์žˆ๋‹ค!

 

Member ํ…Œ์ด๋ธ”์—์„œ Team์„ ์กฐํšŒ? Team์—์„œ Member๋ฅผ ์กฐํšŒ?

 

๊ฐ์ฒด ์„ค๊ณ„๋Š” Member ์—์„œ Team์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , Team์—์„œ๋Š” Members๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋„๋ก ์„ค๊ณ„ํ•œ๋‹ค.

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

๋‘˜์€ JOIN์„ ํ†ตํ•ด์„œ ๊ด€๊ณ„๋ฅผ ๋งบ์„ ์ˆ˜ ์žˆ๋‹ค! DB๋Š” ๋ฐฉํ–ฅ์ด ์—†๋‹ค.

 

๋‹ค๋Œ€์ผ ๊ด€๊ณ„์ค‘ ์ผ(1)์˜ ์—”ํ‹ฐํ‹ฐ์— ์ปฌ๋ ‰์…˜์„ ์ถ”๊ฐ€ํ•ด์ค€๋‹ค.

 

@Entity
public class Team {

	@Id @GeneratedValue
    private Long id;
    
    private String name;
    
    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<Member>();
 	
    public void addMember(Member member) {
    	member.setTeam(this);
    	members.add(member);
    }
    
}

 

์—ญ๋ฐฉํ–ฅ์œผ๋กœ ๋ฉค๋ฒ„๋“ค์„ ์กฐํšŒํ•  ์ˆ˜ ์žˆ๋‹ค.

Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();

 

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

DB ํ…Œ์ด๋ธ”์—์„œ๋Š” FK ์„ ์–ธ์œผ๋กœ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋ฅผ ๋งบ์„ ์ˆ˜ ์žˆ๋‹ค. Join์„ ํ†ตํ•ด์„œ ํ…Œ์ด๋ธ”์˜ ๊ด€๊ณ„๋ฅผ ๋ชจ๋‘ ์กฐํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๊ฐ์ฒด์™€ ํ…Œ์ด๋ธ”๊ฐ„์— ์—ฐ๊ด€๊ด€๊ณ„๋ฅผ ๋งบ๋Š” ์ฐจ์ด

 

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

Member < - > Team (์–‘๋ฑกํ–ฅ)

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

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์˜ ์—ฐ๊ด€๊ด€๊ณ„ 1๊ฐœ (๋‹จ๋ฐฉํ–ฅ)

Team -> Member์˜ ์—ฐ๊ด€๊ด€๊ณ„ 1๊ฐœ (๋‹จ๋ฐฉํ–ฅ)

 

๊ฐ์ฒด์˜ ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋‹จ๋ฐฉํ–ฅ ๊ด€๊ณ„ 2๊ฐœ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๋‹ค.

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

 

๋‘˜ ์ค‘ ํ•˜๋‚˜๋กœ ์™ธ๋ž˜ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผํ•œ๋‹ค.  => ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด !

 

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

๋ฉค๋ฒ„์˜ ํŒ€๊ฐ’์„ ์—…๋ฐ์ดํŠธํ• ๋•Œ, FK๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๊ฒŒ ํ• ๊ฒƒ์ธ์ง€?

ํŒ€์˜ members๋ฅผ ์—…๋ฐ์ดํŠธ ํ–ˆ์„๋•Œ FK๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋Š”์ง€?

 

DB์—์„œ๋Š” FK๊ฐ’๋งŒ ์—…๋ฐ์ดํŠธ ํ•˜๋ฉด ๋˜์—ˆ๋Š”๋ฐ! ์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„ ๋งคํ•‘์—์„œ๋Š” ํ•œ๋ช…์„ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค!

๋ˆ„๊ฐ€! ์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์ด ๊ด€๋ฆฌํ•˜๋Š” ์ชฝ์œผ๋กœ ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๋‹ค.

 

์–‘๋ฐฉํ–ฅ ๋งคํ•‘ ๊ทœ์น™

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

- ์ฃผ์ธ์ด ์•„๋‹Œ ์ชฝ์€ ์ฝ๋Š” ๊ฒƒ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. 

- mappedBy : ์ฃผ์ธ์ด ์•„๋‹Œ ์ชฝ์ด ์ฃผ์ธ์„ ์ง€์ •ํ•œ๋‹ค. 

์ฃผ์ธ

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

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์€ ๋น„์ฆˆ๋‹ˆ์Šค์ ์œผ๋กœ ์ ‘๊ทผํ•˜๊ธฐ ๋ณด๋‹ค, FK๋ฅผ ๊ฐ€์ง„ ์ชฝ์ด ์ฃผ์ธ์ด ๋˜๋ฉด ๋œ๋‹ค.

 


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

 

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_ID๊ฐ€ NULL์ธ ์ƒํ™ฉ์ด ๋ฐœ์ƒํ•œ๋‹ค.

 

 

์—ฐ๊ด€๊ด€๊ณ„์˜ ์ฃผ์ธ์— ๊ฐ’์„ ์ž…๋ ฅํ•ด์•ผํ•œ๋‹ค.

๊ตณ์ด team์˜ members์ปฌ๋ ‰์…˜์— ๋ฉค๋ฒ„๋ฅผ ๋„ฃ์–ด์ฃผ์ง€ ์•Š์•„๋„, ์ง€์—ฐ๋กœ๋”ฉ์„ ํ†ตํ•ด์„œ ํ•ด๋‹น ๋ฉค๋ฒ„๋ฅผ ์กฐํšŒํ•ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ,  ์ง„์งœ ๊ฐ์ฒด ์ง€ํ–ฅ์ ์œผ๋กœ ๊ณ ๋ คํ•œ๋‹ค๋ฉด ํ•ญ์ƒ ์–‘์ชฝ ๋‹ค ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š” ๊ฒƒ์ด ๋งž๋‹ค.

(ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ• ๋•Œ, em.flush(), em.clear()๊ฐ€ ๋˜์ง€ ์•Š์€ ์ƒํ™ฉ์—์„œ 1์ฐจ ์ƒํƒœ์—์„œ ์บ์‹œ๋œ ์ƒํƒœ์—์„œ ์กฐํšŒํ•˜๋ ค๊ณ  ํ• ๋•Œ NPE๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ์ ๋“ค์ด ์กด์žฌํ•จ)

 

Team team = new Team();
team.setName("TeamA");
em.persist(team);

Member member = new Member();
member.setName("member1");
em.persist(member);

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

// ์ด ๋™์ž‘์ด ์ˆ˜ํ–‰๋˜์ง€ ์•Š์œผ๋ฉด FK๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์ง€ ์•Š์€ 1์ฐจ์บ์‹œ์—๋งŒ ์˜์†ํ™” ๋œ ์ƒํƒœ.
em.flush();
em.clear();

Team findTeam = em.find(Team.class, team.getId());
List<Member> findMembers = findTeam.getMembers();

for (Member m : findMembers) {
   // flush, clear๊ฐ€ ์ผ์–ด๋‚œ ํ›„์—๋Š” ํŒ€์˜ Members์— ๋„ฃ์–ด์ฃผ์ง€ ์•Š์•˜์ง€๋งŒ, ์กฐํšŒ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค
   System.out.println(m.getUsername());
}

tx.commit();

 

์—ฐ๊ด€๊ด€๊ณ„ํŽธ์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅ

ํŽธ์˜ ๋ฉ”์†Œ๋“œ์—์„œ๋Š” ์ฃผ์ธ์ชฝ์—์„œ ์—ฐ๊ด€๊ด€๊ณ„์˜ ๊ฐ’์„ ์„ค์ •ํ• ๋•Œ, ์—ญ๋ฐฉํ–ฅ ๊ฐ’๋„ ํ•จ๊ป˜ ์„ค์ •ํ•ด์ค€๋‹ค. ๋ฉ”์†Œ๋“œ๋ฅผ ์›์ž์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ์— ์„ธํŠธ๋กœ ๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด ์‹ค์ˆ˜ํ•  ์ผ์ด ์ค„์–ด๋“ ๋‹ค.

 

class Member {
  ...
       
   public void changeTeam(Team team) {
       this.team = team;
       team.getMembers().add(this);
  }
}
class Team {

	public addMember(Member member) {
    	member.setTeam(this);
        members.add(member);
    }
}

 

์–‘๋ฐฉํ–ฅ ์—ฐ๊ด€๊ด€๊ณ„ ๋งคํ•‘์‹œ ์ฃผ์˜ํ•  ์ 

lombok์ด ์ž๋™์œผ๋กœ ๋งŒ๋“œ๋Š” toString()๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ง๊ฒƒ.

 

Member์˜ toString() 

@Override
   public String toString() {
       return "Member{" +
           "id=" + id +
           ", username='" + username + '\'' +
           ", team=" + team +
           '}';
  }

 

Team์˜ toString()

@Override
   public String toString() {
       return "Team{" +
           "id=" + id +
           ", name='" + name + '\'' +
           ", members=" + members +
           '}';
  }

 

Member์˜ toString()์„ ํ˜ธ์ถœํ•˜๋Š” ์ˆœ๊ฐ„ Team์˜ toString()์˜ members๊ฐ€ ํ˜ธ์ถœํ•˜๋Š” ๊ฐ member์˜ toString() ๋•Œ๋ฌธ์— ๋ฌดํ•œ๋ฃจํ”„๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค. ์Šคํƒ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ๊ฐ€ ๋ฐœ์ƒํ•จ.

 

JSON ์ƒ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

์–‘๋ฐฉํ–ฅ ๊ด€๊ณ„์˜ Entity๋ฅผ JSON์œผ๋กœ ์‹œ๋ฆฌ์–ผ๋ผ์ด์ฆˆ ํ•˜๋Š” ์ˆœ๊ฐ„ ๋ฌดํ•œ๋ฃจํ”„์— ๋น ์ง€๊ฒŒ ๋œ๋‹ค.

์ปจํŠธ๋กค๋Ÿฌ์—์„œ๋Š” ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ ˆ๋Œ€ ์ง์ ‘ ๋ฐ˜ํ™˜ํ•˜๋ฉด์•ˆ๋œ๋‹ค.

์—”ํ‹ฐํ‹ฐ > JSON์‹œ ๋ฌดํ•œ๋ฃจํ”„ ๊ฑธ๋ฆฐ๋‹ค.

์‹ค๋ฌด์—์„œ๋Š” DTO๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ฐ˜ํ™˜ํ•˜๋ฉด JSON ์ƒ์„ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ธํ•œ ๋ฌธ์ œ๋Š” ์—†์–ด์งˆ ๊ฒƒ

 

์ฐธ์กฐ

https://www.inflearn.com/course/ORM-JPA-Basic

 

์ž๋ฐ” ORM ํ‘œ์ค€ JPA ํ”„๋กœ๊ทธ๋ž˜๋ฐ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

JPA๋ฅผ ์ฒ˜์Œ ์ ‘ํ•˜๊ฑฐ๋‚˜, ์‹ค๋ฌด์—์„œ JPA๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๊ธฐ๋ณธ ์ด๋ก ์ด ๋ถ€์กฑํ•˜์‹  ๋ถ„๋“ค์ด JPA์˜ ๊ธฐ๋ณธ ์ด๋ก ์„ ํƒ„ํƒ„ํ•˜๊ฒŒ ํ•™์Šตํ•ด์„œ ์ดˆ๋ณด์ž๋„ ์‹ค๋ฌด์—์„œ ์ž์‹ ์žˆ๊ฒŒ JPA๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., - ๊ฐ•์˜ ์†Œ๊ฐœ | ์ธํ”„๋Ÿฐ

www.inflearn.com

 

728x90