๐Ÿ’พ Database

[JPA] ๊ฐ’ ํƒ€์ž…(๊ธฐ๋ณธ๊ฐ’, @Embedded, ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜)

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

๋ชฉ์ฐจ

     

     

     

     

    ๊ธฐ๋ณธ๊ฐ’ ํƒ€์ž…

    ๋‹จ์ˆœํžˆ ๊ฐ’์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์ด๋‚˜ ๊ฐ์ฒด์ด๋‹ค.

    ์‹๋ณ„์ž๊ฐ€ ์—†๊ณ  ๊ฐ’๋งŒ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ๋ณ€๊ฒฝ ์ถ”์  ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

     

     

    ์ž„๋ฒ ๋””๋“œํƒ€์ž…

    ์—”ํ‹ฐํ‹ฐ์ด์ง€๋งŒ, ๊ธฐ๋ณธ๊ฐ’์ฒ˜๋Ÿผ ๋‹จ์ˆœํžˆ ๊ฐ’์œผ๋กœ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค.

     = ๋ณ€๊ฒฝ ์ถ”์  ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

     

    @Embeddable : ๊ฐ’์„ ์ •์˜ํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œ

    @Embedded : ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œ

    ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ํ•„์ˆ˜๋กœ ๋งŒ๋“ค์–ด์ฃผ์–ด์•ผํ•œ๋‹ค.

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        private String city;
        private String street;
        private String zipcode;
    }

    city, street, zipcode๋ฅผ Address๋ผ๋Š” ์—”ํ‹ฐํ‹ฐ๋กœ ๋ฌถ์–ด๋‚ด์ž

     

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @Embedded
        private Address address;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
    }
    
    @Embeddable
    public class Address{
        private String city;
        private String street;
        private String zipcode;
    }

     

     

    ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์œผ๋กœ ๋ฌถ์–ด๋‚ด๋„ ํ…Œ์ด๋ธ” ๋งคํ•‘์€ ๋˜‘๊ฐ™๋‹ค.

     

    ์ž„๋ฒ ๋””๋“œํƒ€์ž… VS @MappedSuperclass

    @MappedSuperclass๋Š” "์ƒ์†"์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์ค‘์ƒ์†์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

    @Embedded๋Š” "๊ฐ’"์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ™์€ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๋‹ค์ค‘์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @Embedded
        private Address homeaddress;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
        
        @Embedded
        private Address workaddress;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
    }
    
    @Embeddable
    public class Address{
        private String city;
        private String street;
        private String zipcode;
    }

    ์ด๋•Œ๋Š” homeAddress์™€ workAddress์˜ ์ปฌ๋Ÿผ๋ช…์ด ๊ฒน์น˜๊ธฐ๋•Œ๋ฌธ์— 

    @AttributeOverrides, @AttributeOverride๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ปฌ๋Ÿผ๋ช…์„ ์žฌ์ •์˜ ํ•ด์•ผํ•œ๋‹ค.

     

     

    @AttributeOverride

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @Embedded
        private Address homeaddress;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
        
        @Embedded
        @AttributeOverrides({
        	@AttributeOverride(name="city", column=@Column(name="work_city")),
            @AttributeOverride(name="street", column=@Column(name="work_street")),
            @AttributeOverride(name="zipcode", column=@Column(name="work_zipcode"))
        })
        private Address workaddress;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
    }
    
    @Embeddable
    public class Address{
        private String city;
        private String street;
        private String zipcode;
    }

     

     

     

    ๊ฐ’ํƒ€์ž…๊ณผ ๋ถˆ๋ณ€๊ฐ์ฒด

    ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…๊ฐ’์€ ์—ฌ๋Ÿฌ ์—”ํ‹ฐํ‹ฐ์—์„œ ๊ณต์œ ํ•˜๋ฉด ์œ„ํ—˜ํ•˜๋‹ค.

    Address address = new Address("city", "street", "1000");
    
    Member member1 = new Member();
    member1.setName("member1");
    member1.setAddress(address);	//โญโญโญ
    em.persist(member1);
    
    Member member2 = new Member();
    member2.setName("member2");
    member2.setAddress(address);	//โญโญโญ
    em.persist(member2);
    
    member1.getAddress().setCity("newCity");
    
    System.out.println(member1.getAddress().getCity());	//newCity
    System.out.println(member2.getAddress().getCity());	//newCity 	โ—โ—โ—โ—โ—

     

     

     

    ๋ฐ˜๋“œ์‹œ ๊ฐ’์„ ๋ณต์‚ฌํ•ด์„œ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค!!!!!!!

    ๊ธฐ๋ณธํƒ€์ž…์€ ๊ฐ’์„ ๋ณต์‚ฌํ•˜์ง€๋งŒ, ๊ฐ์ฒดํƒ€์ž…์€ ์ฐธ์กฐ๋ฅผ ์ „๋‹ฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์žŠ์ง€๋ง์ž

    Address address = new Address("city", "street", "1000");
    
    Member member1 = new Member();
    member1.setName("member1");
    member1.setAddress(address);	//โญโญโญ
    em.persist(member1);
    
    Address copyAddress = new Address(address.getCity(), address.getStreet(), address.getZipcode());
    
    Member member2 = new Member();
    member2.setName("member2");
    member2.setAddress(copyAddress);	//โญโญโญ
    em.persist(member2);
    
    member1.getAddress().setCity("newCity");
    
    System.out.println(member1.getAddress().getCity());	//newCity
    System.out.println(member2.getAddress().getCity());	//City 	โ—โ—โ—โ—โ—

     

    ํ•˜์ง€๋งŒ.. ๋ˆ„๊ตฐ๊ฐ€ member2.setAddress(address); ๋ฅผ... ์‹ค์ˆ˜๋กœ ์ž…๋ ฅํ•˜๋ฉด ์–ด๋–กํ•˜์ง€?!

    ๊ฐ์ฒดํƒ€์ž…์„ ์•„์˜ˆ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“ค์–ด๋ฒ„๋ฆฌ๋ฉด ๋œ๋‹ค.

     

     

    ๋ถˆ๋ณ€๊ฐ์ฒด : ์ƒ์„ฑ ์ดํ›„ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ๊ฐ์ฒด

    ์ƒ์„ฑ์ž๋กœ๋งŒ ๊ฐ’์„ ์„ค์ •ํ•˜๊ณ , setter๋ฅผ ๋งŒ๋“ค์ง€ ์•Š์œผ๋ฉด ๋œ๋‹ค.

    ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, ์•„์˜ˆ copy๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์ž

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @Embedded
        private Address homeaddress;	//์ž„๋ฒ ๋””๋“œ ํƒ€์ž…
        
        ...getter๋งŒ ์ƒ์„ฑ...	//โญโญโญ
        
        public void copyAddress(){
        	~~~
        }
    }
    
    @Embeddable
    public class Address{
        private String city;
        private String street;
        private String zipcode;
    }

     

     

     

    ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜

    ํšŒ์›์ด ์ข‹์•„ํ•˜๋Š” ์Œ์‹์„ ๋ฐ›์œผ๋ ค๋ฉด ์–ด๋–ป๊ฒŒํ•˜๋ฉด๋ ๊นŒ?

    Member์— List<String> foods ์ด๋Ÿฐ์‹์œผ๋กœ ์ถ”๊ฐ€ํ•˜๋ฉด๋œ๋‹ค.

    ํ…Œ์ด๋ธ”์—์„œ๋Š” ์ปฌ๋ ‰์…˜์„ ์ €์žฅํ•  ์ˆ˜ ์—†๊ธฐ๋•Œ๋ฌธ์— member_id์™€ food(varchar)๋ฅผ ๊ฐ€์ง„ ํ…Œ์ด๋ธ”์„ ํ•˜๋‚˜ ์ƒ์„ฑํ•ด์•ผํ•œ๋‹ค.

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @ElementCollection
        @CollectionTable(name ="favorite_food",
        	joinColumns = @JoinColumn(name="member_id")
        )
        @Column(name = "food_name")
        private Set<String> favoriteFoods = new HashSet<>();	//์ปฌ๋ ‰์…˜ ํƒ€์ž…
        
        
        @ElementCollection
        @CollectionTable(name ="address",
        	joinColumns = @JoinColumn(name="member_id")
        )
        @Column(name = "food_name")
        private List<Address> addressList = new ArrayList<>();	//์ปฌ๋ ‰์…˜ ํƒ€์ž…
       
    }

     

    ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜์€ ์˜์†์„ฑ ์ „์ด + ๊ณ ์•„ ๊ฐ์ฒด ์ œ๊ฑฐ ๊ธฐ๋Šฅ์„ ํ•„์ˆ˜๋กœ ๊ฐ€์ง„๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

    ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜๋„ ์ง€์—ฐ๋กœ๋”ฉ ์ „๋žต ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

    โš  ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜์— ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ๋ฐœ์ƒํ•˜๋ฉด JPA๋Š” ์ฃผ์ธ ์—”ํ‹ฐํ‹ฐ์™€ ์—ฐ๊ด€๋œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๊ณ ,

    ๊ฐ’ ํƒ€์ž… ์ปฌ๋ ‰์…˜์— ์žˆ๋Š” ํ˜„์žฌ ๊ฐ’์„ ๋ชจ๋‘ ๋‹ค์‹œ ์ €์žฅํ•œ๋‹ค.

    โš  ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜์„ ๋งคํ•‘ํ•˜๋Š” ํ…Œ์ด๋ธ”์€ ๋ชจ๋“  ์ปฌ๋Ÿผ์„ ๋ฌถ์–ด์„œ ๊ธฐ๋ณธํ‚ค๋กœ ๊ตฌ์„ฑํ•ด์•ผํ•œ๋‹ค. ๊ทธ๋ž˜์•ผ null๊ณผ ์ค‘๋ณต์ €์žฅ์„ ๋ง‰์„ ์ˆ˜ ์žˆ๋‹ค.

     

     

    => ๋˜๋„๋ก ๊ฐ’ํƒ€์ž… ์ปฌ๋ ‰์…˜ ๋Œ€์‹  ์ผ๋Œ€๋‹ค ๊ด€๊ณ„๋กœ ํ’€์–ด๋‚ด์ž

         ์ฐจ๋ผ๋ฆฌ ์—”ํ‹ฐํ‹ฐ๋กœ ํ•œ๋ฒˆ ๋žฉํ•‘ํ•˜์ž.

     

    @Entity
    public class Member{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        private String name;	//๊ฐ’ ํƒ€์ž…
        
        @ElementCollection
        @CollectionTable(name ="favorite_food",
        	joinColumns = @JoinColumn(name="member_id")
        )
        @Column(name = "food_name")
        private Set<String> favoriteFoods = new HashSet<>();	//์ปฌ๋ ‰์…˜ ํƒ€์ž…
        
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
        @JoinColumn(name = "member_id")
        private List<AddressEntity> addressList = new ArrayList<>();	//์ปฌ๋ ‰์…˜ ํƒ€์ž…
    }
    
    @Entity
    @Table(name = "address")
    public class AddressEntity{
        @Id @GeneratedValue
        @Column(name="member_id")
        private Long id;		//๊ฐ’ ํƒ€์ž…
        
        private Address address;
    }

     

     

     

     

     

    ๊ฐ’ํƒ€์ž…์€ ๊ฐ’ํƒ€์ž…์ด๋ผ ํŒ๋‹จ๋  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์ž.

    ์—”ํ‹ฐํ‹ฐ์™€ ๊ฐ’ ํƒ€์ž…์„ ํ˜ผ๋™ํ•ด์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ๊ฐ’ ํƒ€์ž…์œผ๋กœ ๋งŒ๋“ค๋ฉด ์•ˆ๋œ๋‹ค.

    ์‹๋ณ„์ž๊ฐ€ ํ•„์š”ํ•˜๊ณ , ์ง€์†ํ•ด์„œ ๊ฐ’์„ ์ถ”์ ํ•˜๊ณ  ๋ณ€๊ฒฝํ•ด์•ผํ•œ๋‹ค๋ฉด ์—”ํ‹ฐํ‹ฐ์ด๋‹ค.

     

     

     

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