κΈ°λ³Έκ° νμ
JPA μ λ°μ΄ν° νμ λΆλ₯
- μν°ν° νμ
- @Entity λ‘ μ μνλ κ°μ²΄
- λ°μ΄ν°κ° λ³ν΄λ μλ³μλ‘ μ§μν΄μ μΆμ κ°λ₯
- μ) νμ μν°ν°μ ν€λ λμ΄ κ°μ λ³κ²½ν΄λ μλ³μλ‘ μΈμ κ°λ₯
- κ° νμ
- int, Integer, String μ²λΌ λ¨μν κ°μΌλ‘ μ¬μ©νλ μλ° κΈ°λ³Έ νμ μ΄λ κ°μ²΄
- μλ³μκ° μκ³ κ°λ§ μμΌλ―λ‘ λ³κ²½ μ μΆμ λΆκ°
- μ) μ«μ 100μ 200μΌλ‘ λ³κ²½νλ©΄ μμ ν λ€λ₯Έ κ°μΌλ‘ λ체
κ° νμ λΆλ₯
- κΈ°λ³Έκ° νμ
- μλ° κΈ°λ³Έ νμ
- λνΌ ν΄λμ€
- String
- μλ² λλ νμ
- 컬λ μ κ° νμ
κΈ°λ³Έκ° νμ
- μ) String name, int age
- μλͺ
μ£ΌκΈ°λ₯Ό μν°ν°μ μμ‘΄
- μ) νμμ μμ νλ©΄ μ΄λ¦, λμ΄ νλλ ν¨κ» μμ
- κ° νμ
μ 곡μ νλ©΄ X
- μ) νμ μ΄λ¦ λ³κ²½ μ λ€λ₯Έ νμμ μ΄λ¦λ ν¨κ» λ³κ²½λλ©΄ μλ¨
μλ² λλ νμ (μ€μ)
μλ°μμ μ°λ¦¬λ μλ‘μ΄ κ° νμ
μ μ§μ μ μν μ μλ€. JPA λ μ΄λ₯Ό μλ² λλ νμ
μ΄λΌκ³ νλ€.
μ£Όλ‘ κΈ°λ³Έ κ° νμ
μ λͺ¨μμ λ§λ€μ΄μ λ³΅ν© κ° νμ
μ΄λΌκ³ λ νλ€.
μ΄λ κ² λ§λ€μ΄μ§ μλ² λλ νμ
μ int
String
κ³Ό κ°μ κ° νμ
μΌλ‘ μ·¨κΈλλ€.
μμ
νμ μν°ν°λ μ΄λ¦, 근무 μμμΌ, 근무 μ’
λ£μΌ, μ£Όμ λμ, μ£Όμ λ²μ§, μ£Όμ μ°νΈ λ²νΈλ₯Ό κ°μ§λ€.
μ΄λ₯Ό μΆμν νλ©΄ β νμ μν°ν°λ μ΄λ¦, 근무 κΈ°κ°, μ§ μ£Όμλ₯Ό κ°μ§λ€.
μλ² λλ νμ μ¬μ©λ²
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Embedded
private Period workPeriod;
@Embedded
private Address homeAddress;
}
@Embeddable
κ° νμ μ μ μνλ κ³³μ νμ@Embedded
κ° νμ μ μ¬μ©νλ κ³³μ νμ- κΈ°λ³Έ μμ±μ νμ
μλ² λλ νμ μ μ₯μ
- μ¬μ¬μ©
- λμ μμ§λ
Period.isWork()
μ²λΌ ν΄λΉ κ° νμ λ§ μ¬μ©νλ μλ―Έ μλ λ©μλλ₯Ό λ§λ€ μ μμ- μλ² λλ νμ μ ν¬ν¨ν λͺ¨λ κ° νμ μ, κ° νμ μ μμ ν μν°ν°μ μλͺ μ£ΌκΈ°λ₯Ό μμ‘΄ν¨
μλ² λλ νμ κ³Ό ν μ΄λΈ 맀ν
μλ² λλ νμ
μ μν°ν°μ κ°μΌ λΏμ΄λ€. μ¦, μλ² λλ νμ
μ μ¬μ©νκΈ° μ κ³Ό νμ 맀ννλ ν
μ΄λΈμ κ°λ€.
μλ² λλ νμ
μ ν΅ν΄ κ°μ²΄μ ν
μ΄λΈμ μμ£Ό μΈλ°νκ²(fine-grained) 맀ννλ κ²μ΄ κ°λ₯νλ€.
λλ¬Έμ, μ μ€κ³ν ORM μ ν리μΌμ΄μ
μ 맀νν ν
μ΄λΈμ μλ³΄λ€ ν΄λμ€μ μκ° λ λ§λ€.
μλ² λλ νμ κ³Ό μ°κ΄κ΄κ³
@AttributeOverride: μμ± μ¬μ μ
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "name")
private String name;
@Embedded
private Period workPeriod;
@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;
}
ν μν°ν°μμ κ°μ κ° νμ
μ μ¬μ©νλ€λ©΄? μ»¬λΌ λͺ
μ΄ μ€λ³΅λκΈ° λλ¬Έμ μλ¬κ° λ°μνλ€.
@AttributeOverrides
@AttributeOverride
λ₯Ό μ¬μ©ν΄μ μ»¬λΌ λͺ
μμ±μ μ¬μ μνμ¬ μ¬μ©νμ.
μλ² λλ νμ κ³Ό null
μλ² λλ νμ
μ κ°μ΄ null
μ΄λ©΄ 맀νν μ»¬λΌ κ°μ λͺ¨λ null
μ΄ λ€μ΄κ°λ€.
κ° νμ κ³Ό λΆλ³ κ°μ²΄
κ° νμ 곡μ μ°Έμ‘°
μλ² λλ νμ
κ°μ κ° νμ
μ μ¬λ¬ μν°ν°μμ 곡μ νλ©΄ κ°μ μΈμ€ν΄μ€λ₯Ό μ¬μ©νκ³ μκΈ° λλ¬Έμ λ³κ²½μ λͺ¨λ μν₯μ λ°μ μ μλ λΆμμ©μ΄ λ°μν μ μμ΄ μννλ€.
κ° νμ 볡μ¬
κ° νμ
μ μ€μ μΈμ€ν΄μ€μΈ κ°μ 곡μ νλ κ²μ μνν¨νκΈ° λλ¬Έμ μΈμ€ν΄μ€λ₯Ό 볡μ¬ν΄μ μ¬μ©νλ€.
κ°μ²΄ νμ μ νκ³
int a = 10;
int b = a;
b = 4;
// a = 10, b = 4
Address a = new Address("Old");
Address b = a;
b.setCity("New");
// a = New, b = New
νμ κ°μ 볡μ¬ν΄μ μ¬μ©νλ©΄ 곡μ μ°Έμ‘°λ‘ μΈν΄ λ°μνλ λΆμμ©μ νΌν μ μλ€. λ¬Έμ λ μλ² λλ νμ μ²λΌ μ§μ μ μν κ° νμ μ μλ°μ κΈ°λ³Έ νμ μ΄ μλλΌ κ°μ²΄ νμ μ΄λ€. μλ° κΈ°λ³Έ νμ μ κ°μ λμ νλ©΄ κ°μ 볡μ¬νλ€. κ°μ²΄ νμ μ μ°Έμ‘° κ°μ μ§μ λμ νλ κ²μ λ§μ λ°©λ²μ΄ μλ€. μ¦, κ°μ²΄μ 곡μ μ°Έμ‘°λ νΌν μ μλ€.
λΆλ³ κ°μ²΄
κ°μ²΄ νμ μ μμ ν μ μκ² λ§λ€λ©΄ λΆμμ©μ μμ² μ°¨λ¨ν μ μλ€. λλ¬Έμ κ° νμ μ λΆλ³ κ°μ²΄λ‘ μ€κ³ν΄μΌνλ€. μ¬κΈ°μ λΆλ³ κ°μ²΄λ μμ± μ΄ν μ λ κ°μ λ³κ²½ν μ μλ κ°μ²΄λ₯Ό μλ―Ένλ€.
κ° νμ μ λΉκ΅
// a μ b λ κ°μμΌ νλ€
int a = 10;
int b = 10;
Address a = new Address("μμΈμ");
Address b = new Address("μμΈμ");
κ° νμ μ μΈμ€ν΄μ€κ° λ¬λΌλ κ·Έ μμ κ°μ΄ κ°μΌλ©΄ κ°μ κ²μΌλ‘ λ΄μΌ νλ€.
λμΌμ± λΉκ΅μ λλ±μ± λΉκ΅
λμΌμ± λΉκ΅λ μΈμ€ν΄μ€μ μ°Έμ‘° κ°μ λΉκ΅νλ€. (==
μ¬μ©)
λλ±μ± λΉκ΅λ μΈμ€ν΄μ€μ κ°μ λΉκ΅νλ€. (equals()
μ¬μ©)
κ° νμ
μ a.equals(b)
λ₯Ό μ¬μ©ν΄μ λλ±μ± λΉκ΅λ₯Ό μνν΄μΌ νλ€.
κ° νμ
μ equals()
λ©μλλ₯Ό μ μ νκ² μ¬μ μνμ¬ μ¬μ©ν΄μΌ νλ€. (μ£Όλ‘ λͺ¨λ νλλ₯Ό μ¬μ©)
κ° νμ 컬λ μ (μ€μ)
@Entity
public class Member {
@ElementCollection
@CollectionTable(name = "FAVORITE_FOOD", joinColumns = @JoinColumn(name = "MEMBER_ID"))
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection
@CollectionTable(name = "ADDRESS", joinColumns = @JoinColumn(name = "MEMBER_ID"))
private List<Address> addressHistory = new ArrayList<>();
}
Hibernate:
create table ADDRESS (
MEMBER_ID bigint not null,
city varchar(255),
street varchar(255),
zipcode varchar(255)
)
Hibernate:
create table FAVORITE_FOOD (
MEMBER_ID bigint not null,
favoriteFoods varchar(255)
)
Hibernate:
create table Member (
id bigint generated by default as identity,
city varchar(255),
street varchar(255),
zipcode varchar(255),
name varchar(255),
WORK_CITY varchar(255),
WORK_STREET varchar(255),
WORK_ZIPCODE varchar(255),
endDate timestamp,
startDate timestamp,
primary key (id)
)
Hibernate:
alter table ADDRESS
add constraint FKsuulxb5rmrxvb83yr43ox86wn
foreign key (MEMBER_ID)
references Member
Hibernate:
alter table FAVORITE_FOOD
add constraint FKjchfnr69biisfgjdpoe82rpa4
foreign key (MEMBER_ID)
references Member
κ° νμ
컬λ μ
μ κ° νμ
μ νλ μ΄μ μ μ₯ν λ μ¬μ©νλ©°, @ElementCollection
μ @CollectionTable
μ μ¬μ©νμ¬ DB μ μ μ₯νλ€.
DB λ 컬λ μ
μ κ°μ ν
μ΄λΈμ μ μ₯ν μ μκΈ° λλ¬Έμ, 컬λ μ
μ μ μ₯νκΈ° μν λ³λμ ν
μ΄λΈμ΄ νμνλ€.
κ° νμ 컬λ μ μ μ₯
Set<String> favoriteFood = Set.of("μΉν¨", "μ‘±λ°", "νΌμ");
List<Address> addressHistory = List.of(new Address("city1", "street1", "1000"), new Address("city1", "street2", "2000"));
Member member = new Member(null, "member1", favoriteFood, addressHistory);
em.persist(member);
ν΄λΉ μ½λλ₯Ό μ€νν΄λ³΄λ©΄ μλμ κ°μ 쿼리λ₯Ό λ³Ό μ μλ€.
Hibernate:
/* insert hellojpa.Member
*/ insert
into
Member
(id, name)
values
(null, ?)
Hibernate:
/* insert collection
row hellojpa.Member.addressHistory */ insert
into
ADDRESS
(MEMBER_ID, city, street, zipcode)
values
(?, ?, ?, ?)
Hibernate:
/* insert collection
row hellojpa.Member.addressHistory */ insert
into
ADDRESS
(MEMBER_ID, city, street, zipcode)
values
(?, ?, ?, ?)
Hibernate:
/* insert collection
row hellojpa.Member.favoriteFoods */ insert
into
FAVORITE_FOOD
(MEMBER_ID, favoriteFoods)
values
(?, ?)
Hibernate:
/* insert collection
row hellojpa.Member.favoriteFoods */ insert
into
FAVORITE_FOOD
(MEMBER_ID, favoriteFoods)
values
(?, ?)
Hibernate:
/* insert collection
row hellojpa.Member.favoriteFoods */ insert
into
FAVORITE_FOOD
(MEMBER_ID, favoriteFoods)
values
(?, ?)
μ¬κΈ°μ μ μ μλ μ¬μ€μ Member
μν°ν°λ§ persist()
νμμλ λΆκ΅¬νκ³ λͺ¨λ κ° νμ
컬λ μ
λ€μ΄ μ μ₯λλ κ²μ μ μ μλ€.
μ΄λ κ° νμ
컬λ μ
μ΄ λ€λ₯Έ ν
μ΄λΈμ μ μ₯ λλλΌλ κ·Έλ₯ κ° νμ
κ³Ό λ€λ₯Ό λ°κ° μλ€λ μλ―Έμ΄λ©° μλͺ
μ£ΌκΈ°λ₯Ό Member
μν°ν°μ λμΌνκ² κ°λλ€λ κ²μ μ μ μλ€.
μ¦, List<Address>
λ μ¬μ€ String
κ³Ό λ€λ₯Ό λ°κ° μλ€λ κ²μ΄λ€.
κ° νμ
컬λ μ
μ μμμ± μ μ΄(Cascade All
) + κ³ μ κ°μ²΄ μ κ±° κΈ°λ₯μ νμλ‘ κ°μ§λ€κ³ λ³Ό μ μλ€.
κ° νμ 컬λ μ μ‘°ν
em.flush();
em.clear();
Member findMember = em.find(Member.class, member.getId());
Hibernate:
select
member0_.id as id1_6_0_,
member0_.name as name2_6_0_
from
Member member0_
where
member0_.id=?
Member
μν°ν° μ‘°ν μ μμ κ°μ 쿼리λ₯Ό λ³Ό μ μλ€.
μ΄λ₯Ό ν΅ν΄ κ° νμ
컬λ μ
λ μ§μ° λ‘λ© μ λ΅μ΄ μ¬μ©λκ³ μλ€λ κ²μ μ μ μλ€.
μ΄λ @ElementCollection
μ fetch
μ κΈ°λ³Έ μ€μ μ΄ LAZY
λ‘ μ€μ λμ΄μκΈ° λλ¬Έμ΄λ€.
κ° νμ 컬λ μ μμ
Member findMember = em.find(Member.class, member.getId());
findMember.getFavoriteFoods().remove("μΉν¨");
findMember.getFavoriteFoods().add("νμ");
findMember.getAddressHistory().remove(new Address("city1", "street1", "1000"));
findMember.getAddressHistory().add(new Address("new", "new", "1111"));
κ° νμ
컬λ μ
μ μμ νλ μμ
μ μμ κ°μ΄ μ€νν΄λ³΄μ.
Address
κ°μ κ²½μ° λλ±μ± λΉκ΅λ₯Ό μν΄ equals
hashcode
λ₯Ό κΌ μ¬μ μ ν΄μ£Όμ΄μΌ νλ€.
Hibernate:
/* delete collection hellojpa.Member.addressHistory */ delete
from
ADDRESS
where
MEMBER_ID=?
Hibernate:
/* insert collection
row hellojpa.Member.addressHistory */ insert
into
ADDRESS
(MEMBER_ID, city, street, zipcode)
values
(?, ?, ?, ?)
Hibernate:
/* insert collection
row hellojpa.Member.addressHistory */ insert
into
ADDRESS
(MEMBER_ID, city, street, zipcode)
values
(?, ?, ?, ?)
Hibernate:
/* delete collection row hellojpa.Member.favoriteFoods */ delete
from
FAVORITE_FOOD
where
MEMBER_ID=?
and favoriteFoods=?
Hibernate:
/* insert collection
row hellojpa.Member.favoriteFoods */ insert
into
FAVORITE_FOOD
(MEMBER_ID, favoriteFoods)
values
(?, ?)
μ½λλ₯Ό μ€ννκ³ λλ©΄ μ΄λ° μΏΌλ¦¬κ° λ μκ°λ κ²μ νμΈν μ μλ€.
Address
μ κ²½μ° μμ νλλ₯Ό μ κ±°νκ³ νλλ₯Ό μΆκ°νλ 쿼리λ₯Ό κΈ°λνμ§λ§, λͺ¨λ ν
μ΄λΈμ λ°μ΄λ²λ¦¬κ³ λ κ°μ INSERT
μΏΌλ¦¬λ¬Έμ΄ λ μκ°λ κ²μ νμΈν μ μλ€.
κ° νμ 컬λ μ μ μ μ½μ¬ν
κ° νμ μ μν°ν°μ λ€λ₯΄κ² μλ³μ κ°λ μ΄ μ‘΄μ¬νμ§ μκΈ° λλ¬Έμ, κ°μ λ³κ²½νλ©΄ μΆμ μ΄ μ΄λ ΅λ€. λλ¬Έμ, κ° νμ 컬λ μ μ λ³κ²½μ΄ λ°μνλ©΄ μ£ΌμΈ μν°ν°μ μ°κ΄λ λͺ¨λ λ°μ΄ν°λ₯Ό μμ νκ³ , κ° νμ 컬λ μ μ μλ νμ¬ κ°μ λͺ¨λ λ€μ μ μ₯νλ€. κ° νμ 컬λ μ μ 맀ννλ ν μ΄λΈμ λͺ¨λ 컬λΌμ λ¬Άμ΄μ κΈ°λ³Έ ν€λ₯Ό ꡬμ±ν΄μΌ νλ€.
κ° νμ 컬λ μ λμ
μ€λ¬΄μμλ μν©μ λ°λΌ κ° νμ 컬λ μ λμ μ μΌλλ€ κ΄κ³λ₯Ό κ³ λ €νλ κ²½μ°κ° λ§λ€. μΌλλ€ κ΄κ³λ₯Ό μν μν°ν°λ₯Ό λ§λ€κ³ , μ¬κΈ°μμ κ° νμ μ μ¬μ©νλ λ°©μμ΄λ€. μμμ± μ μ΄μ κ³ μ κ°μ²΄ μ κ±°λ₯Ό ν΅ν΄ κ° νμ 컬λ μ μ²λΌ μ¬μ©νλ€.
@Entity
@Table(name = "ADDRESS")
public class AddressEntity {
@Id
@GeneratedValue
private Long id;
private Address address;
}
μ 리
- μν°ν° νμ
μ νΉμ§
- μλ³μκ° μλ€
- μλͺ μ£ΌκΈ° κ΄λ¦¬
- 곡μ ν μ μλ€
- κ° νμ
μ νΉμ§
- μλ³μκ° μλ€
- μλͺ μ£ΌκΈ°λ₯Ό μν°ν°μ μμ‘΄
- 곡μ νμ§ μλ κ²μ΄ μμ (볡μ¬ν΄μ μ¬μ©)
- μ¦, λΆλ³ κ°μ²΄λ‘ λ§λλ κ²μ΄ μμ
- κ° νμ μ μ λ§ κ° νμ μ΄λΌ νλ¨λ λλ§ μ¬μ©
- μν°ν°μ κ° νμ μ νΌλν΄μ μν°ν°λ₯Ό κ° νμ μΌλ‘ λ§λ€λ©΄ μλ¨
- μλ³μκ° νμνκ³ , μ§μν΄μ κ°μ μΆμ , λ³κ²½ν΄μΌ νλ€λ©΄ μν°ν°λ‘ ꡬμ±νμ