๐Ÿ’พ Database

[JPA] ํ”„๋ก์‹œ์™€ ์ฆ‰์‹œ๋กœ๋”ฉ, ์ง€์—ฐ๋กœ๋”ฉ / ์˜์†์„ฑ ์ „์ด์™€ ๊ณ ์•„๊ฐ์ฒด

์—ฐ_์šฐ๋ฆฌ 2022. 2. 21. 22:18
๋ฐ˜์‘ํ˜•

๋ชฉ์ฐจ

     

     

    em.getReference() ๋ฉ”์„œ๋“œ

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;
        private String name;
        @ManyToOne
        @JoinColumn(name="team_id")
        private Team team;
        
        private static void printMember(Member member){
        	System.out.println("member : " + member);
        }
        
        private static void printMemberAndTeam(Member member){
        	System.out.println("member : " + member);
            System.out.println("team : " + member.getTeam());
        }
    }
    
    @Entity
    public class Team{
        @Id @GeneratedValue
        @Column(name="team_id")
        private Long id;
        private String name;
    }

    Member๋ฅผ DB์—์„œ ์ฐพ์•„์™€์„œ ์ถœ๋ ฅํ•œ๋‹ค๊ณ  ํ•˜์ž.

    Team์˜ ๋‚ด์šฉ์„ ์ถœ๋ ฅํ•œ๋‹ค๋ฉด printMemberAndTeam()์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

    Team์˜ ๋‚ด์šฉ์„ ์ถœ๋ ฅํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด printMember()๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

     

    printMember๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ JPA์—์„œ Team์˜ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ž์›์˜ ๋‚ญ๋น„ ์•„๋‹๊นŒ?

    ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ํ”„๋ก์‹œ์ด๋‹ค.

     

     

    JPA๋Š” DB์—์„œ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” em.find()๋ฉ”์„œ๋“œ์™€

    ์กฐํšŒ๋ฅผ ์ตœ๋Œ€ํ•œ ๋ฏธ๋ฃจ๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์งœ(ํ”„๋ก์‹œ) ์—”ํ‹ฐํ‹ฐ๋ฅผ ์กฐํšŒํ•˜๋Š” em.getReference()๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    em.getReference๋Š” DB์— ์ฟผ๋ฆฌ๊ฐ€ ์•ˆ๋‚˜๊ฐ€๋Š”๋ฐ ์กฐํšŒ๊ฐ€ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

     

    Member member = new Member();
    member.setName("hello");
    em.persist(member);
    em.flush();
    //insert๋ฌธ ์ „์†ก
    em.clear();
    
    Member findMember = em.getReference(Member.class, member.getId());
    
    System.out.println("findMember : " + findMember.getClass());
    //findMember : class hellojpa.Member$HibernateProxy$nMvq2opM
    
    System.out.println("findMember.name : " + findMember.getName());
    //select๋ฌธ ์ „์†ก
    //findMember.name : hello

    getReference๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ํด๋ž˜์Šค๋ฅผ ์กฐํšŒํ•ด๋ณด๋ฉด $HibernateProxy$~~ ๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์กฐํšŒ๋œ๋‹ค.

     

     

     

    ํ”„๋ก์‹œ๋ž€?

     - ์‹ค์ œ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„์„œ ๋งŒ๋“ค์–ด์ง„๋‹ค.

     - ์‹ค์ œ ๊ฐ์ฒด์˜ ์ฐธ์กฐ(target)์„ ๋ณด๊ด€ํ•œ๋‹ค.

     - ํ”„๋ก์‹œ ๊ฐ์ฒด๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ํ”„๋ก์‹œ๋Š” ์‹ค์ œ ๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

     - ํ”„๋ก์‹œ ๊ฐ์ฒด๋Š” ์ฒ˜์Œ ์‚ฌ์šฉํ•  ๋•Œ ํ•œ๋ฒˆ๋งŒ ์ดˆ๊ธฐํ™”๋œ๋‹ค.

     - ์ดˆ๊ธฐํ™”๋Š” ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ๋ฅผ ํ†ตํ•ด DB์—์„œ ์กฐํšŒ ํ›„ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ”„๋ก์‹œ์—๊ฒŒ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์ด๋‹ค.

     - ==๋น„๊ต ๋Œ€์‹  instance of ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

     - ํ”„๋ก์‹œ๊ฐ€ ์ดˆ๊ธฐํ™”๋œ๋‹ค ํ•ด๋„ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ๋กœ ๋ฐ”๋€Œ๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด ์—”ํ‹ฐํ‹ฐ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

     - ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์— ์ฐพ๋Š” ์—”ํ‹ฐํ‹ฐ๊ฐ€ ์žˆ๋‹ค๋ฉด em.getReference()๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์‹ค์ œ ์—”ํ‹ฐํ‹ฐ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

     - ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์˜ ๋„์›€์„ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ์ค€์˜์† ์ƒํƒœ์ผ ๋•Œ, ํ”„๋ก์‹œ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด LazyInitializationException ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.

     

     

    ์ฆ‰์‹œ ๋กœ๋”ฉ : FetchType.EAGER

    printMemberAndTeam()์ฒ˜๋Ÿผ Member์™€ Team์ด ์—ฐ๊ฒฐ๋˜์–ด์žˆ์„๋•Œ

    ํ•ญ์ƒ Member์™€ Team์„ ์กฐ์ธํ•ด์„œ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

    ์ฃผ์˜!!

     - ๊ฐ€๊ธ‰์  ์ง€์—ฐ ๋กœ๋”ฉ๋งŒ ์‚ฌ์šฉํ•˜์ž.

     - ์ฆ‰์‹œ ๋กœ๋”ฉ์„ ์ ์šฉํ•˜๋ฉด ์—ฐ๊ด€๊ด€๊ณ„์˜ ๋ชจ๋“  ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•ด์„œ ๊ฐ€์ ธ์˜ค๊ธฐ๋•Œ๋ฌธ์—

        Member๋งŒ ์ถœ๋ ฅํ•œ๋‹คํ•ด๋„ JPA์—์„œ๋Š” ๋ชจ๋“  ํ…Œ์ด๋ธ”์„ ์กฐํšŒํ•œ๋‹ค

     - ์ฆ‰์‹œ๋กœ๋”ฉ์€ JPQL์—์„œ N+1๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚จ๋‹ค. 

       select m from Member m ํ–ˆ์„ ๋•Œ, Member๋ฅผ ๊ฐ€์ ธ์™”๋”๋‹ˆ Team์ด ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋‹ค

       ์•—! Team๋„ ์กฐํšŒํ•ด์•ผํ•ด! ํ•˜๊ณ  Team์„ ์กฐํšŒํ•˜๋Š” ์ฟผ๋ฆฌ๋ฅผ ์ „์†กํ•˜๊ฒŒ๋œ๋‹ค. (Select๋ฌธ์ด 2๋ฒˆ ํ˜ธ์ถœ๋จ)

     

     

    ์ง€์—ฐ ๋กœ๋”ฉ : FetchType.LAZY

    printMember()์ฒ˜๋Ÿผ Member์™€ Team์ด ์—ฐ๊ฒฐ๋˜์–ด์žˆ์ง€๋งŒ

    Member์— ๋Œ€ํ•œ ๊ฒƒ๋งŒ ๋จผ์ € ์กฐํšŒํ•˜๊ณ , Team์€ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ๋˜์–ด์„œ์•ผ ์กฐํšŒํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

     

     

     

    ์˜์†์„ฑ ์ „์ด CASCADE

    ํŠน์ • ์—”ํ‹ฐํ‹ฐ๋ฅผ ์˜์†์ƒํƒœ๋กœ ๋งŒ๋“ค ๋•Œ, ์—ฐ๊ด€๋œ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์˜์†์ƒํƒœ๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ

    ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ €์žฅํ•  ๋•Œ, ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋„ ํ•จ๊ป˜ ์ €์žฅํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

    cascade = CascadeType.PERSIST

     

    ๊ฒŒ์‹œํŒ - ์ฒจ๋ถ€ํŒŒ์ผ ๊ด€๊ณ„์ฒ˜๋Ÿผ "๊ฒŒ์‹œํŒ"์—์„œ๋งŒ "์ฒจ๋ถ€ํŒŒ์ผ"์„ ๊ด€๋ฆฌํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋ฉด ์œ ์šฉํ•˜๋‹ค.

    ์ฒจ๋ถ€ํŒŒ์ผ์„ ๋‹ค๋ฅธ ์—”ํ‹ฐํ‹ฐ์—์„œ๋„ ๊ด€์—ฌํ•˜๊ฒŒ๋œ๋‹ค๋ฉด, ์‚ฌ์šฉํ•˜์ง€ ๋ง์ž

     

     

     

    ๊ณ ์•„๊ฐ์ฒด

    ๋ถ€๋ชจ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๊ด€๊ณ„๊ฐ€ ๋Š์–ด์ง„ ์ž์‹ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ž๋™์œผ๋กœ ์‚ญ์ œํ•œ๋‹ค.

    orphanRemoval = true

     

    parent.getChildList().remove(0) ํ•˜๋Š” ๊ฒฝ์šฐ

    ์‚ญ์ œ๋œ child์— ๋Œ€ํ•ด Delete์ฟผ๋ฆฌ๊ฐ€ ์ „์†ก๋œ๋‹ค.

    ๋ฐ˜์‘ํ˜•
    • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
    • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
    • ํŠธ์œ„ํ„ฐ ๊ณต์œ ํ•˜๊ธฐ
    • ๊ตฌ๊ธ€ ํ”Œ๋Ÿฌ์Šค ๊ณต์œ ํ•˜๊ธฐ
    • ์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ