[JPA] κ° νμ - μλ² λλ κ° νμ , 컬λ μ κ° νμ
by rlaehddnd0422JPAμ λ°μ΄ν° νμ μλ ν¬κ² μν°ν° νμ , κ° νμ μΌλ‘ λλ μ μμ΅λλ€.
// μν°ν° νμ
@Entity
public class Member{
@Id
private Long id; // κ° νμ
private String name; // κ° νμ
@Embedded
private Address address; // μλ² λλ κ° νμ
private List<Address> addressHistory; // 컬λ μ
κ° νμ
}
- μν°ν° νμ : λ¨μν @Entityλ‘ μ μνλ κ°μ²΄
- κ° νμ
: λ¨μν μμΉ μ 보
- λ¨μ κ° νμ : int, double, String, Integer
- μλ² λλ κ° νμ : μ¬μ©μ μ μ νμ @Embedded
- 컬λ μ κ° νμ : List, Set, Map κ³Ό κ°μ 컬λ μ μ μ¬μ©ν νμ
κ° νμ νΉμ§
- μν°ν° νμ μ μλ³μ κ°μ ν΅ν΄ μΆμ μ΄ κ°λ₯νλ€λ μ μ λ°ν΄, κ° νμ μ λ¨μν μμΉμ 보μ΄κΈ° λλ¬Έμ μλ³μλ‘ μΆμ μ΄ λΆκ°λ₯ν©λλ€.
- μλͺ
μ£ΌκΈ°λ₯Ό μν°ν°μ μμ‘΄ν©λλ€. μ¦, μν°ν°κ° μμ λλ©΄ κ°νμ
μ μλμΌλ‘ κ°μ΄ μ κ±°λ©λλ€.
- μν°ν°λ μμ±, μμν, μλ©Ένλ μλͺ μ£ΌκΈ°κ° μμ΅λλ€.
μλ² λλ κ° νμ ( λ³΅ν© κ° νμ )
μλ‘μ΄ κ° νμ μ μ§μ μ μν΄μ μ¬μ©νλ νμ μ λλ€. μλ² λλ νμ λ λ§μ°¬κ°μ§λ‘ κ° νμ μ ν¬ν¨νκ³ μμ΅λλ€.
@Embeddable
public class Address {
private String city; // κ° νμ
private String street; // κ° νμ
...
}
Member μν°ν°μ city, streetμΌλ‘ μμΈ λ°μ΄ν°λ₯Ό κ°λ κ²λ³΄λ€ μλ² λλ νμ μ μ¬μ©ν΄μ μ μνλ κ²μ΄ κ°λ μ±μ΄λ, κ°μ²΄μ§ν₯ μΈ‘λ©΄μμ μ’μ΅λλ€.
λΏλ§ μλλΌ μλ‘ μ μν κ° νμ μΈ Addressλ ν΄λμ€μ΄κΈ° λλ¬Έμ μ¬μ¬μ©λ κ°λ₯νκ³ , μμ§λλ μμ£Ό λμ΅λλ€.
μλ² λλ κ° νμ μ κΈ°λ³Έ μμ±μκ° νμμ μΌλ‘ μμ΄μΌ ν©λλ€.
μλ² λλ κ° νμ μ κ° νμ μ ν¬ν¨ν λΏλ§ μλλΌ μν°ν°λ₯Ό μ°Έκ³ νλ κ²λ κ°λ₯ν©λλ€.
@Embeddable
public class Address {
private String city; // κ° νμ
private String street; // κ° νμ
...
@Embedded
private ZipCode zipcode; // μλ² λλ νμ
ν¬ν¨
@ManyToOne
private State state; // μν°ν° μ°Έμ‘°
}
+ @AttributeOverrideλ₯Ό μ¬μ©ν΄ 맀ν μ 보λ₯Ό μ¬μ μ ν μ μμ΅λλ€.
@Entity
public class Member{
@Id @GeneratedValue
private Long id;
private String name;
@Embedded
private Address address;
@Embedded
@AttributeOverrides({
@AttributeOverride(name="city", column=@Column(name="COMPANY_CITY")),
@AttributeOverride(name="street", column=@Column(name="COMPANY_STREET")),
@AttributeOverride(name="zipcode", column=@Column(name="COMPANY_ZIPCODE"))})
private Address companyAddress;
}
- 맀νμ 보λ₯Ό μ¬μ μνλ κ²½μ°λ λλ¬ΌκΈ΄ ν©λλ€λ§, μλ² λλ νμ μ ν μν°ν°μμ μ¬μ¬μ©νλ κ²½μ° @AttributeOverrideλ‘ λ§€νμ 보(컬λΌλͺ )μ μ¬μ μ ν μ μμ΅λλ€.
+ μλ² λλ νμ μ nullλ‘ μ€μ νλ©΄ νμ λ΄λΆ λͺ¨λ κ° νμ μ΄ nullλ‘ μ€μ λ©λλ€.
member.setAddress(null);
em.persist(member);
// -> member.address.city = null
// -> member.address.street = null
// -> member.address.zipcode = null
μλ² λλ κ° νμ μ¬μ©μ μ£Όμν μ
μλ² λλ κ° νμ μ¬μ© μ μ£Όμν΄μΌ ν μ μ΄ μμ΅λλ€.
1. κ° νμ μ 곡μ λμ΄μλ μλ©λλ€.
- νμ1.address.city = "OldCity"
- add = νμ1.getAddress()
- νμ2.setAddress(add)
- νμ2.address.city = "NewCity"
- νμ1μ cityλ NewCityλ‘ λ³κ²½λ¨ ( 곡μ μ°Έμ‘° λΆμμ© )
μλ² λλ κ° νμ λ κ°μ²΄μ΄κΈ° λλ¬Έμ 곡μ λκ² λλ©΄ μλ°μμλ μΈμ€ν΄μ€ κ°μ 곡μ νλ κ²μ΄ μλλΌ μ°Έμ‘°λ₯Ό 곡μ νκ² λ©λλ€.
μ°Έμ‘°λ₯Ό 곡μ νκ² λλ©΄ μλ² λλ νμ λ΄λΆ κ°μ΄ λ³κ²½λλ©΄ ν΄λΉ μΈμ€ν΄μ€λ₯Ό 곡μ ν΄μ μ¬μ©νλ μν°ν°λ€μ κ°μ΄ μ λΆ Update λλ λΆμμ©μ΄ λ°μν©λλ€.
곡μ μ°Έμ‘°λ‘ λ°μνλ λ²κ·Έλ μ λ§ μ°Ύμλ΄κΈ° μ΄λ ΅κΈ° λλ¬Έμ, μλ² λλ νμ μ μΈμ€ν΄μ€λ 곡μ ν΄μ μ¬μ©νμ§ μλλ‘ ν©μλ€.
λ¨νΈμ μΈ ν΄κ²°λ°©λ² : 곡μ νλ λμ μΈμ€ν΄μ€λ₯Ό 볡μ¬ν΄μ μ¬μ©νλ λ°©λ²μ΄ μμ΅λλ€.
μλ°λ κΈ°λ³Έ κ° νμ μ κ°μ 볡μ¬ν΄μ λκΈ°μ§λ§, κ°μ²΄ νμ μ μ°Έμ‘°λ§ λκΉλλ€.
νμ§λ§ λ³λμ λ©μλλ‘ ν΄λΉ κ°μ²΄ νμ μ΄ μ°Έμ‘°κ° μλ μΈμ€ν΄μ€μ κ°μ λκΈ°λλ‘ κ΅¬νν΄μ 볡μ¬ν μ μμ΅λλ€.
member.setAddress(new Address("μ μ£Ό", "κΈμλ", "λͺ
λ₯1κΈΈ");
Address address = member.getAddress();
Address address2 = address.clone(); // clone() λ©μλμ μ°Έμ‘°κ° μλ μΈμ€ν΄μ€μ κ°μ 볡μ¬νλλ‘ κ΅¬ν
address.setZipcode("λͺ
λ₯2κΈΈ");
member2.setAddress(address2);
νμ§λ§ μ΄κ²μ΄ 곡μ μ°Έμ‘°λ₯Ό λ§λ κ·Όλ³Έμ μΈ ν΄κ²°μ± μ μλμ£ . 곡μ μ°Έμ‘°λ₯Ό λ§μΌλ €λ©΄ κ·Όλ³Έμ μΌλ‘ κ°μ²΄λ₯Ό λΆλ³νκ² ν΄μΌν©λλ€.
κ·Όλ³Έμ μΈ ν΄κ²°λ°©λ² : μμ μ λ©μλ μ κ±°.
@Embedded
public class Address{
private String city;
private String street;
private String zipcode;
public Address(String city,String street,String zipcode)
{
this.city = city;
this.street = street;
this.zipcode = zipcode;
}
// setter X
}
κ°μ²΄λ₯Ό λΆλ³νκ² νλ€.. κ°μ²΄λ₯Ό λΆλ³νκ² νλ €λ©΄ ν λ² μμ±λ κ°μ²΄μ μμ μ λ§μΌλ©΄ λ©λλ€.
μ½κ² λ§ν΄μ, κΈ°λ³Έ μμ±μλ§ λ§λ€κ³ setterλ μ¬μ©νμ§ μλ κ²μ΄μ£ .
κ°μ²΄λ₯Ό λΆλ³νκ² λ§λ€λ©΄ κ°μ μμ ν μ μμΌλ―λ‘ λΆμμ©μ μμ²μ μ°¨λ¨ν μ μμ΅λλ€. λ°λΌμ κ° νμ μ κ°λ₯ν λΆλ³κ°μ²΄λ‘ μ€κ³νλλ‘ ν©μλ€.
2. μλ² λλ κ° νμ λΉκ΅ μ equalsμ hashCode λ©μλλ₯Ό μ¬μ μ ν΄μ£Όμ΄μΌ ν©λλ€.
μλ² λλ κ° νμ μ κ²°κ΅ κ°μ²΄μ λλ€.
μλ°μμλ κΈ°λ³Έ κ° νμ μ λν΄μ λΉκ΅ν λ, λλ±μ±μ λΉκ΅νκ³ , κ°μ²΄ νμ μ λν΄ λΉκ΅ν λλ λλ±μ±μ λΉκ΅ν©λλ€.
μ¬κΈ°μ λμΌμ±μ΄λ μΈμ€ν΄μ€μ κ°μ λΉκ΅νλ€λ κ²μ΄κ³ , λλ±μ±μ μΈμ€ν΄μ€μ μ°Έμ‘° κ°μ λΉκ΅νλ€λ λ»μ λλ€.
μΌλ°μ μΌλ‘ μ°λ¦¬λ λ κ°μ λΉκ΅ν λ μ°Έμ‘°κ°μ λΉκ΅νλ κ²μ΄ μλλΌ, μΈμ€ν΄μ€κ° λ΄ν¬νκ³ μλ κ° κ·Έ μ체λ₯Ό λΉκ΅ν©λλ€. νμ§λ§ μλ°λ κ°μ²΄μ λν΄μλ κΈ°λ³Έμ μΌλ‘ λλ±μ±μ λΉκ΅νλ€κ³ νμ΅λλ€.
λ°λΌμ μ°λ¦¬κ° λ μλ² λλ κ° νμ μ λΉκ΅ν λ λλ±μ±μ΄ μλ λμΌμ±μ κΈ°μ€μΌλ‘ λΉκ΅νκ³ μΆλ€κ³ νλ©΄ equals, hashCode λ©μλλ₯Ό μ¬μ μν΄ μ€μΌλ‘μ¨, λͺ¨λ νλμ κ°μ λΉκ΅νλλ‘ κ΅¬νν΄μ λμΌμ±μ λΉκ΅νλλ‘ μ€μ ν΄μ£Όμ΄μΌ ν©λλ€.
How to Override
κ° νμ 컬λ μ
κ° νμ μ νλμ΄μ μ μ₯ν λ 컬λ μ μ 보κ΄νμ¬ μ»¬λ μ μ κ° νμ μ²λΌ μ¬μ©ν μ μμ΅λλ€.
μ΄ λ @ElementCollection , @CollectionTable μ΄λ Έν μ΄μ μ΄ μ¬μ©λ©λλ€.
@Entity
public class Member {
@Id
private Long id;
private String name;
@Embedded // μλ² λλ κ° νμ
private Address address;
@ElementCollection
@CollectionTable(name = "ADDRESS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
@Column(name="HISTORY_HOME")
private List<Address> addressHistory = new ArrayList<Address>();
...
}
- @ElementCollection : 컬λ μ κ° νμ 맀νμ μν΄ μ¬μ©λλ μ΄λ Έν μ΄μ
- 컬λ μ
μ Tμ 컬λ μ
μΌλ‘ κ°μ§κΈ° λλ¬Έμ λ³λμ ν
μ΄λΈμ μΆκ°νκ³ ν
μ΄λΈμ 맀νν΄μΌ ν©λλ€.
- @CollectionTable : 컬λ μ κ° νμ μ ν μ΄λΈκ³Ό 맀νν΄μ£Όλ μ΄λ Έν μ΄μ μΌλ‘ μ΄ μ΄λ Έν μ΄μ μ ν΅ν΄ 컬λ μ κ³Ό ν μ΄λΈμ 맀νν μ μμ΅λλ€. ( μ΄ μ΄λ Έν μ΄μ μλ΅ μ κΈ°λ³Έκ°(μν°ν°μ΄λ¦_컬λ μ μμ±μ΄λ¦)μΌλ‘ μ€μ λ ν μ΄λΈκ³Ό μλ 맀νν©λλ€. )
κ° νμ 컬λ μ μ μ₯ μ μμμ± μ μ΄ + κ³ μ κ°μ²΄ μ κ±° κΈ°λ₯μ μλμΌλ‘ κ°μ§κ³ μμ΅λλ€.
μν°ν°λ₯Ό μμν ν΄λ΄ μλ€.
@Entity
public class Member {
@Id
private Long id;
private String name;
@Embedded // μλ² λλ κ° νμ
private Address address;
@ElementCollection
@CollectionTable(name = "ADDRESS",
joinColumns = @JoinColumn(name = "MEMBER_ID"))
@Column(name="HISTORY_HOME")
private List<Address> addressHistory = new ArrayList<Address>();
...
}
member.setName("kim");
member.setAddress(new Address("μ μ£Ό","κΈμ","λͺ
λ₯1"));
member.getAddressHistory().add(new Address("μ μ£Ό","κ°μ¬","82"));
em.persist(member);
persist νΈμΆ ν commitνμ¬ flushνκ² λλ©΄ 2λ²μ SQLμ΄ μ€νλ©λλ€.
insert into MEMBER (id, name, city, street, zipcode) values(1, 'kim', 'μ μ£Ό', 'κΈμ', 'λͺ
λ₯1');
insert into ADDRESS (id, city, street, zipcode) values(1,'μ μ£Ό', 'κ°μ¬', '82');
JPAλ κ° νμ λ ν¨κ» μμν νκΈ° λλ¬Έμ κ° νμ 컬λ μ κ³Ό 맀νλ ν μ΄λΈμλ insert sqlμ΄ μ€νλ©λλ€.
+ κ° νμ 컬λ μ μ μ‘°νν λλ λΉμ°ν ν¨μΉ μ λ΅μ μ¬μ©ν μ μλλ° JPAλ κΈ°λ³Έμ μΌλ‘ κ° νμ 컬λ μ μ μ§μ°λ‘λ©(LAZY)λ‘ μ€μ ν΄ λμμ΅λλ€.
Member member = em.find(Member.class, 1L);
List<Address> addressHistory = member.getAddressHistory();
addressHistory.get(0); // μ€μ μ¬μ© μ νΈμΆνλ LAZY μ λ΅μ΄ κΈ°λ³Έ μ μ©.
κ° νμ 컬λ μ μ κΈ°λ³Έμ μΌλ‘ μ§μ°λ‘λ©μΌλ‘ μ€μ λμ΄ μκΈ° λλ¬Έμ, μ€μ 컬λ μ μ μ¬μ©ν λ SELECT SQLμ 1λ² νΈμΆν©λλ€.
+ κ° νμ 컬λ μ μ 컬λ μ μ λ³κ²½ μ¬ν λ°μ μ μ°κ΄λ λͺ¨λ λ°μ΄ν°λ₯Ό μμ νκ³ , λ³κ²½ μ¬νμΌλ‘ λ€μ μ μ₯ν©λλ€.
κ° νμ 컬λ μ μ 보κ΄λ κ° νμ λ€μ λ³λμ ν μ΄λΈμ 보κ΄λ©λλ€.
λ°λΌμ μ¬κΈ°μ 보κ΄λ κ° νμ μ κ°μ΄ λ³κ²½λλ©΄ λ°μ΄ν°λ² μ΄μ€μ μλ μλ³Έ λ°μ΄ν°λ₯Ό μ°ΎκΈ° μ΄λ ΅λ€λ λ¬Έμ κ° μμ΅λλ€.
JPAλ μ΄ λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ κ° νμ 컬λ μ μ λ³κ²½μ¬νμ΄ μκΈ°λ©΄, κ° νμ 컬λ μ κ³Ό 맀νλ ν μ΄λΈμ λͺ¨λ λ°μ΄ν°λ₯Ό μμ νκ³ , νμ¬ κ° νμ 컬λ μ κ°μ²΄μ μλ λͺ¨λ κ°μ λ°μ΄ν°λ² μ΄μ€μ μ μ₯ν©λλ€.
Memberm member = em.find(Member.class, 100L);
List<Address> addressHistory = member.getAddressHistory();
addressHistory.add(new Address('μ μ£Ό','μ§1','κΈΈ1'));
addressHistory.add(new Address('μ μ£Ό','μ§2','κΈΈ2'));
em.persist(member);
// commit ν μ€νλλ SQL
select from member where member_id = 100
// κΈ°μ‘΄μ λͺ¨λ λ°μ΄ν°λ₯Ό μμ
delete from address where member_id = 100
// λ€μ μ μ₯
insert into address (member_id, city, street, zipcode) values(100L, ...)
insert into address (member_id, city, street, zipcode) values(100L, ...)
λ°λΌμ μ€λ¬΄μμλ κ° νμ 컬λ μ μ΄ λ§€νλ ν μ΄λΈμ λ°μ΄ν°κ° λ§λ€λ©΄ κ° νμ 컬λ μ μ μ¬μ©νλ κ²λ³΄λ€ μν°ν° νμ μ μ¬μ©νμ¬ μΌλλ€ κ΄κ³λ‘ 맀νν΄μ£Όλ κ²μ΄ μ’μ΅λλ€.
@Entity
public class Member {
@Id
private Long id;
private String name;
@Embedded // μλ² λλ κ° νμ
private Address address;
// μμμ± μ μ΄, κ³ μ κ°μ²΄ μ κ±° μ΅μ
μΆκ°ν΄μ κ° νμ
컬λ μ
μ²λΌ 맀ν
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "MEMBER_ID")
private List<AddressHistory> addressHistory = new ArrayList<AddressHistory>();
...
}
@Entity
public class AddressHistory{
@Id
@GeneratedValue
private Long id;
@Embedded Address address;
}
<μ 리>
- μν°ν° νμ μ μλ³μκ° μμ΄ μΆμ μ΄ κ°λ₯νμ§λ§ κ° νμ μ μλ³μλ‘ μΆμ μ΄ λΆκ°λ₯ν©λλ€.
- μν°ν° νμ μ μ°Έμ‘° κ°μ 곡μ νμ¬ λ€λ₯Έ μν°ν°μμ μΌλ§λ μ§ μ‘°νν μ μμ§λ§, κ° νμ μ 곡μ νκ² λλ©΄ μ°Έμ‘° λΆμμ© λ¬Έμ κ° λ°μν μ μκΈ° λλ¬Έμ λΆλ³ κ°μ²΄λ‘ λ§λλ κ²μ΄ μ’μ΅λλ€.
- κ° νμ μ μ λ§ κ° νμ μ΄λΌ νλ¨λ λλ§ μ¬μ©ν©μλ€. μλ³μκ° νμν΄μ μ§μν΄μ κ°μ μΆμ νκ³ κ΅¬λΆνκ³ λ³κ²½ν΄μΌ νλ€λ©΄ μν°ν° νμ μ μ¬μ©ν©μλ€.
- κ° νμ
컬λ μ
μ @ElementCollection, @CollectionTable μ΄λ
Έν
μ΄μ
μΌλ‘ μ¬μ©ν기보λ€, κ° νμ
컬λ μ
μ μΌλλ€ λ§€νμ μμμ± μ μ΄, κ³ μκ°μ²΄ μμ μ΅μ
μ κ³ λ €νλ κ²μ΄ μ’μ΅λλ€.
- why ? κ° νμ 컬λ μ μ λ³κ²½μ¬νμ΄ λ°μνκ² λλ©΄ κ° νμ 컬λ μ μ 맀νλ ν μ΄λΈμ μ°κ΄λ λͺ¨λ λ°μ΄ν°λ₯Ό μμ νκ³ , νμ¬ κ° νμ 컬λ μ κ°μ²΄μ μλ λͺ¨λ κ°μ λ°μ΄ν°λ² μ΄μ€μ λ€μ μ μ₯νκΈ° λλ¬Έμ 맀μ°λ§€μ° λΉν¨μ¨μ .
<μ°Έκ³ μλ£>
'π Backend > Spring Data JPA' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
[JPA] JPQL λ¬Έλ² 2 - μ§ν© λ° μ λ ¬, μ‘°μΈ, νμΉ μ‘°μΈ (0) | 2023.05.09 |
---|---|
[JPA] JPQL λ¬Έλ² 1 - κΈ°λ³Έ λ¬Έλ², νλΌλ―Έν° λ°μΈλ©, νλ‘μ μ , νμ΄μ§ (0) | 2023.05.09 |
[JPA] μμμ± μ μ΄ by Cascade μ΅μ (0) | 2023.05.05 |
[JPA] νλ‘μ(Proxy)μ μ§μ°λ‘λ©(Lazy Loading) (0) | 2023.05.04 |
[JPA] κ³ κΈ λ§€ν : 맀ν μ λ³΄λ§ μ 곡νκΈ° using @MappedSuperClass (0) | 2023.05.03 |
λΈλ‘κ·Έμ μ 보
Study Repository
rlaehddnd0422