JPA

JPA @Embedded, @Embeddable ์‚ฌ์šฉํ•˜๊ธฐ

์•„๋ฆฌ๊ฐ€๋˜๐Ÿ™‚ 2023. 3. 10. 23:54

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

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์€ ๋ณตํ•ฉ ๊ฐ’ ํƒ€์ž…์œผ๋กœ ๋ถˆ๋ฆฌ๋ฉฐ ์ƒˆ๋กœ์šด ๊ฐ’ ํƒ€์ž…์„ ์ง์ ‘ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” JPA์˜ ๋ฐฉ๋ฒ•์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด User์—”ํ‹ฐํ‹ฐ๋Š” id, ์ด๋ฆ„, ์ด๋ฉ”์ผ, ์„ฑ๋ณ„, ์ฃผ์†Œ์ •๋ณด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š”๋ฐ ์ฃผ์†Œ ์ •๋ณด๊ฐ€ ๋„์‹œ, ๊ตฌ, ์ƒ์„ธ์ฃผ์†Œ, ์šฐํŽธ๋ฒˆํ˜ธ ๋“ฑ์œผ๋กœ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปฌ๋Ÿผ์œผ๋กœ ๋‚˜๋ˆ ์ ธ ์žˆ๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -> ์ด๋ ‡๊ฒŒ ์ƒ์„ธํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฐ–๊ณ  ์žˆ๋Š” ๊ฒƒ์€ ๊ฐ์ฒด์ง€ํ–ฅ์ ์ด์ง€ ์•Š์œผ๋ฉฐ ์‘์ง‘๋ ฅ์„ ๋–จ์–ด๋œจ๋ฆฝ๋‹ˆ๋‹ค.
  • ์ด๋Ÿด๋•Œ ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ๋”์šฑ๋” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ธ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
// user.java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NonNull
    private String name;

    @NonNull
    private String email;


    @Enumerated(value = EnumType.STRING)
    private Gender gender;
    
    // ์ฃผ์†Œ ์ •๋ณด
    private String city; // ๋„์‹œ
    private String district; // ๊ตฌ
    private String detail; // ์ƒ์„ธ์ฃผ์†Œ
    private String zipCode; // ์šฐํŽธ๋ฒˆํ˜ธ

}

 

@Embedded, @Embeddable

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์ ์šฉํ•˜๋ ค๋ฉด ์ƒˆ๋กœ์šด Class๋ฅผ ๋งŒ๋“ค๊ณ  ํ•ด๋‹น ํด๋ž˜์Šค์— ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์œผ๋กœ ๋ฌถ์œผ๋ ค๋˜ Attribute๋“ค์„ ๋„ฃ์–ด์ค€ ๋’ค @Embeddable๋ฅผ ๋ถ™์—ฌ์ค˜์•ผํ•ฉ๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ ๋ฐฉ๋ฒ•
    • @Embeddable : ๊ฐ’ ํƒ€์ž…์„ ์ •์˜ํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œ
    • @Embedded : ๊ฐ’ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์— ํ‘œ์‹œ
  • ์•„๋ž˜์˜ ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์ ์šฉํ•œ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ฃผ์†Œ์˜ ๊ด€๋ จ๋œ ์†์„ฑ๋“ค์ด ํ•˜๋‚˜์˜ ํƒ€์ž…์œผ๋กœ ๋ฐ”๊ปด ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ณด๋ฉด ์œ„์˜ ์ฝ”๋“œ๋ณด๋‹ค ๋”์šฑ ๋” ๊ฐ์ฒด์ง€ํ–ฅ์ ์ด๊ณ  ์‘์ง‘๋„ ์žˆ๋Š” ์ฝ”๋“œ๋กœ ๋ฐ”๋€ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
// user.java
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NonNull
    private String name;

    @NonNull
    private String email;


    @Enumerated(value = EnumType.STRING)
    private Gender gender;
    
    @Embedded
    private Address address;

}
// Address.java
@Embeddable
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    // ์ฃผ์†Œ ์ •๋ณด
    private String city; // ๋„์‹œ
    private String district; // ๊ตฌ

    @Column(name = "address_detail")
    private String detail; // ์ƒ์„ธ ์ฃผ์†Œ
    private String zipCode; // ์šฐํŽธ๋ฒˆํ˜ธ
}
// ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•
user.setAddress(new Address("์„œ์šธ์‹œ", "๊ฐ•๋‚จ๊ตฌ", "๊ฐ•๋‚จ๋Œ€๋กœ 123", "16427"));
  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜์—ฌ๋„ ๋™์ผํ•˜๊ฒŒ Column๋“ค์ด ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

@AttributeOverride : ์†์„ฑ๋ช… ์žฌ์ •์˜

  • ๊ฐ™์€ ์ข…๋ฅ˜์˜ Attribute์— ๋Œ€ํ•ด์„œ ์ค‘๋ณต๋œ ์ฝ”๋“œ๋ฅผ ์ ์„ ํ•„์š” ์—†์ด ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์„ฑ์žˆ๊ฒŒ ์„ ์–ธ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ์˜ˆ์‹œ๋กœ๋Š” ํšŒ์‚ฌ์˜ ์ฃผ์†Œ, ์ง‘ ์ฃผ์†Œ์˜ ์ฃผ์†Œ ํ˜•ํƒœ๋Š” ์‹œ, ๊ตฌ, ์ƒ์„ธ์ฃผ์†Œ, ์šฐํŽธ๋ฒˆํ˜ธ๋กœ ๋™์ผํ•˜๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ @Embedded์™€ @AttributeOverrides, @AttributeOverride๋ฅผ ํ†ตํ•ด ํ•˜๋‚˜์˜ class๋ฅผ ์‚ฌ์šฉํ•ด ์—ฌ๋Ÿฌ ํ‘œํ˜„์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (๊ฐ์ฒด์˜ ์žฌํ™œ์šฉ)
  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ์žฌํ™œ์šฉํ•˜๋Š” ๋Œ€์‹  @AttributeOverrides, @AttributeOverride๋ฅผ ์‚ฌ์šฉํ•ด column์˜ ์ด๋ฆ„์„ ์ „๋ถ€ ์žฌ์ •์˜ํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ์— ์ฝ”๋“œ๊ฐ€ ์ง€์ €๋ถ„ํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -> ๊ฐ์ฒด๋ฅผ ์žฌํ™œ์šฉ ํ•˜์ง€ ์•Š๊ณ  ๋”ฐ๋กœ ์„ ์–ธํ•ด์„œ ํ•˜๋Š” ๋Œ€์‹  ๊น”๋”ํ•˜๊ฒŒ ๋ณด์ด๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ง€, ๊ฐ์ฒด์˜ ์žฌํ™œ์šฉ์„ ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ• ์ง€๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฒฐ์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
@Entity
public class User {

.....

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "home_city")), // city๋ฅผ home_city๋ผ๋Š” column๋ช…์œผ๋กœ ์‚ฌ์šฉ
            @AttributeOverride(name = "district", column = @Column(name = "home_district")),
            @AttributeOverride(name = "detail", column = @Column(name = "home_address_detail")),
            @AttributeOverride(name = "zipCode", column = @Column(name = "home_zipCode"))
    })
    private Address homeAddress;

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "city", column = @Column(name = "company_city")),
            @AttributeOverride(name = "district", column = @Column(name = "company_district")),
            @AttributeOverride(name = "detail", column = @Column(name = "company_address_detail")),
            @AttributeOverride(name = "zipCode", column = @Column(name = "company_zipCode"))
    })
    private Address companyAddress;
   
   	.....
}

์ฃผ์˜ํ•  ์ 

    @Embedded
    private Address homeAddress;
    @Embedded
    private Address companyAddress;


ํ•˜๋‚˜์˜ class๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ •๋ณด๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์€๋ฐ ์œ„์™€ ๊ฐ™์ด @AttributeOverrides, @AttributeOverride๋ฅผ ํ†ตํ•ด column๋ช…์„ ์žฌ์ •์˜ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด Repeated column in mapping for entity ์—๋Ÿฌ๊ฐ€ ๋‚˜์˜ค๋‹ˆ ๊ผญ column๋ช…์„ ์žฌ์ •์˜ํ•ด์ค˜์„œ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.


์ž„๋ฒ ๋””๋“œ ํƒ€์ž…๊ณผ null

  • ์ž„๋ฒ ๋””๋“œ ํƒ€์ž… ์ž์ฒด๋ฅผ null๋กœ ์ง€์ •ํ–ˆ์„ ๋•Œ์™€ ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์˜ ์†์„ฑ ๊ฐ’์„ null๋กœ ์„ค์ •ํ–ˆ์„ ๋•Œ๋Š” ๋ชจ๋‘ ํ•ด๋‹น column์˜ ๊ฐ’์ด null๊ฐ’์œผ๋กœ ๋‚˜์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ๊ด€๋ จ column๋“ค์˜ ๊ฐ’์ด ๋ชจ๋‘ null์ธ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ฆ‰, ์ž„๋ฒ ๋””๋“œ ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ null์ธ ๊ฒฝ์šฐ ๋‚ด๋ถ€์˜ ๋ชจ๋“  column์ด null์ธ ๊ฒƒ๊ณผ ๋™์ผํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
    void embedTest() {
        User user1 = new User();
        user1.setName("jaeryeol");
        user1.setHomeAddress(null);
        user1.setCompanyAddress(null);

        userRepository.save(user1);

        User user2 = new User();
        user2.setName("jaeryeol2");
        user2.setHomeAddress(new Address());
        user2.setCompanyAddress(new Address());

        userRepository.save(user2);

        userRepository.findAllRawRecord().forEach(a-> System.out.println(a.values()));
   }
}
๊ฒฐ๊ณผ
User(super=BaseEntity(createdAt=2023-03-09T00:33:51.107644, updatedAt=2023-03-09T00:33:51.107644), id=6, name=jaeryeol, email=null, gender=null, city=null, district=null, detail=null, zipCode=null, homeAddress=null, companyAddress=null)
User(super=BaseEntity(createdAt=2023-03-09T00:33:51.164491, updatedAt=2023-03-09T00:33:51.164491), id=7, name=jaeryeol2, email=null, gender=null, city=null, district=null, detail=null, zipCode=null, homeAddress=null, companyAddress=null)