JPA #9 ๊ฐ ํ์ , ์ปฌ๋ ์ , ์๋ฒ ๋๋ ํ์
by JiwonDevJPA์์๋ 2๊ฐ์ง ๋ฐ์ดํฐ ํ์ ์ ์ ๊ณตํ๋ค.
@Entity ๋ ๋ฐ์ดํฐ๊ฐ ๋ณํด๋ ์๋ณ์๋ก ๊ณ์ ์ถ์ ์ด ๊ฐ๋ฅํ๋ค. ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋ณ์๋ก ์ธ์ ๊ฐ๋ฅํ๋ค.
๊ธฐ๋ณธ ๊ฐ ํ์ ์ @Entity ์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ณต์ ํ๋ฉฐ, String, Integer, int ๋ฑ์ ์๋ฏธํ๋ค.
๋จ, ๊ฐ ํ์ ์ ๋ํ ์๋ณ์๋ ๋ฐ๋ก ์กด์ฌํ์ง ์์ผ๋ฏ๋ก JPA์ ๋ณ๊ฒฝ์ถ์ ์ด ๋ถ๊ฐ๋ฅํ๋ค.
์ด๊ฒ ๋ฌด์จ๋ง์ด๋๋ฉด, ์ธ๋ถ์ ๊ฐํ์ ์ ๋ณ๊ฒฝํ ์ ์๋ ์ฐธ์กฐ๊ฐ ์๋ค๋ฉด Side-Effect๊ฐ ๋ฐ์ํ ์ํ์ด ์๋ค๋ ๋ง.
- ๋ญ ์ฌ์ค ์๋ฐ์์ Primitive Type (int, long)์ ์ฐธ์กฐ๊ฐ ๊ณต์ ๊ฐ ๋ถ๊ฐ๋ฅํด์ ๋ณ ์๊ด์ด ์๋ค.
- Integer๋ String์ ๋ํผํ์ ์ ์ฐธ์กฐ๊ฐ์ ๊ณต์ ๊ฐ ๊ฐ๋ฅํ์ง๋ง, ๋ณ๊ฒฝ์ด ๋ถ๊ฐ๋ฅํ๊ฒ ๋งํ์๋ค.
๊ทธ๋์ ์ด๊ฑธ ์ค๋ช ํ๋ ์ด์ ๊ฐ ๋ญ์ฃ ? ๋น์ฐํ๊ฑฐ ์๋์์?
JPA์์ ๊ธฐ๋ณธ๊ฐ ํ์ ๋ง ์ฌ์ฉํ๋ค๋ฉด ์๋ฌด๋ฐ ๋ฌธ์ ๊ฐ ์๋ค.
๊ฐ ํ์ ์ค์๋ Embedded Type, Collection Type์ด ์กด์ฌํ๊ธฐ ๋๋ฌธ์, ์ด ์ฐจ์ด๋ฅผ ๊ผญ ์์์ผํ๋ค.
๐ r๊ฐ ํ์ - Embedded
๊ฐ ํ์ ์ @Entity์ ์๋ช ์ฃผ๊ธฐ์ ์์กดํ๋ค. ์ฆ Entity๊ฐ ์ญ์ ๋๋ฉด ๊ฐ๋ ์ญ์ ๋๋ค. ๋น์ฐํ ์ด์ผ๊ธฐ
๊ฐ ํ์ ์ JPA์์ ๋ณ๊ฒฝ ์ถ์ ์ด ๋ถ๊ฐ๋ฅํ๋ค. ์ฆ ์๋์ ๊ฐ์ Side-Effect๋ฅผ ์กฐ์ฌํด์ผํ๋ค.
* ์ฐธ๊ณ ๋ก EmbeddedType ๋ํ ํ๋ก์๋ฅผ ์ด์ฉํ๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ์์ฑ์๊ฐ ํ์์ ์ด๋ค.
์์ผ๋ฉด JpaSystemException: No default constructor for entity ์์ธ ๋ฐ์
EmbeddedType์ด ๋ญ์์ฃ ?
๐ @Embedded (์ปดํฌ๋ํธ)
์ฐ๋ฆฌ๊ฐ @Entity๋ฅผ ๋ฌด์ง์ฑ์ผ๋ก ์ค๊ณํ๋ฉด ์๋์ ๋น์ทํ๊ฒ ๋์จ๋ค.
// ์๋ฒ ๋๋ ํ์
์ฌ์ฉํ์ง ์์์ ๋
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
private String name;
// ๊ทผ๋ฌด ๊ธฐ๊ฐ
LocalDate startDate;
LocalDate endDate;
// ์ง ์ฃผ์ ํํ
private String city;
private String street;
private String zipcode;
// ...
}
ํ์์ด ์์ ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง ์ด์ ๋ ์๋์ ๊ฐ์ด ์ค๊ณํ๊ณ ์ ํ๊ธฐ ๋๋ฌธ์ด๋ค.
"ํ์ ์ํฐํฐ๋ ์ด๋ฆ, [ ๊ทผ๋ฌด ๊ธฐ๊ฐ ], [ ์ง ์ฃผ์ ]๋ฅผ ๊ฐ์ง๋ค."
์ค์ ๋ฐ์ดํฐ๋ '๊ทผ๋ฌด๊ธฐ๊ฐ', '์ง ์ฃผ์'๋ผ๋ ํ๋์ ๊ฐ์ผ๋ก ๋ค๋ฃจ๊ธฐ์๋ ๊น๋ค๋กญ๋ค. ๊ทธ๋์ ์ด๋ฐ Entity๊ฐ ๋ง๋ค์ด์ง๋ค.
"ํ์ ์ํฐํฐ๋ ์ด๋ฆ, [๊ทผ๋ฌด ์์์ผ, ๊ทผ๋ฌด ์ข
๋ฃ์ผ], [์ฃผ์ ๋์, ์ฃผ์ ๋ํธ์, ์ฐํธ ๋ฒํธ]๋ฅผ ๊ฐ์ง๋ค."
๋ฌด์ธ๊ฐ ์ด์ํ์ง ์์๊ฐ? ํ์์ด '์ง ์ฃผ์'๊ฐ ํ์ํ๊ฑฐ์ง '์์ธ', '906ํธ' ์ด๋ฐ ๊ฐ์ด ๋จ๋ ์ผ๋ก ํ์ํ ๊ฒฝ์ฐ๊ฐ ์์๊น?
์๋ ์ ์ด์, [ ์ง ์ฃผ์ ] ๋ ํ๋์ ๋ฐ์ดํฐ๋ก ๋ด์ผํ ๊ฑฐ ๊ฐ์๋ฐ, ์ฌ๊ธฐ์ ํฌํจ๋ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ํ์์ด ๊ฐ์ง๊ณ ์๋๊ฒ ๊ฐ์ฒด์งํฅ์ ์ผ๋ก ์ข์ ์ค๊ณ์ธ์ง ๊ณ ๋ฏผํด๋ณผ ํ์๊ฐ ์๋ค. ์ด๋ ์์ง๋ ฅ์ ๋จ์ด๋จ๋ฆฌ๊ณ , ์ ์ง๋ณด์๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ ๋ค.
โจ ์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด JPA์์๋ @Embedded ํ์ (์ปดํฌ๋ํธ)๋ฅผ ์ ๊ณตํด์ค๋ค.
- ์๋ฒ ๋๋ ํ์ ์ ์ฌ์ฉํ๋ค๊ณ ํด์ DB ํ ์ด๋ธ์ด ๋ ์์ฑ๋์ง๋ ์๋๋ค. ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ๋งคํํด์ ์ฌ์ฉ.
- ํ๋ฒ ๋ง๋ค์ด๋๋ฉด ๋ค๋ฅธ ๊ณณ์์ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. (+ ๋ฐ์ดํฐ์ ์์ง๋๊ฐ ๋์์ง๋ค)
- Embedded ํ์ ๋ด๋ถ์์ ๋ฉ์๋๋ฅผ ํตํด ์๋ฏธ์๋ ์๋ก์ด ๊ฐ ( isMan() )์ ๋ฝ์๋ผ ์ ์๋ค.
// ์๋ฒ ๋๋ ํ์
์ฌ์ฉ
@Entity
public class Member {
@Id @GeneratedVAlue
private Long id;
private String name;
@Embedded
private Period workPeriod; // ๊ทผ๋ฌด ๊ธฐ๊ฐ
@Embedded
private Address homeAddress; // ์ง ์ฃผ์
}
์๋ฒ ๋๋ ํ์ ์ ์๋์ ๊ฐ์ด ์ ์ ๊ฐ๋ฅํ๋ค.
@Embeddable
public class Address {
@Column(name="city") // ๋งคํํ ์ปฌ๋ผ ์ ์ ๊ฐ๋ฅ
private String city;
private String street;
private String zipcode;
public boolean isMetropolitanCity (City city) {
// .. ๊ฐ ํ์
์ ์ํ ๋ฉ์๋๋ฅผ ์ ์ํ ์ ์๋ค
}
}
๋น์ฐํ ์๋ฒ ๋๋ ํ์ ์์์ ๋ค๋ฅธ ์๋ฒ ๋๋ ํ์ ์ ์ฌ์ฉํ ์ ์๋ค.
๊ทธ๋์ ์ ์ค๊ณ๋ JPA Entity๋ ๋ณดํต DB ํ ์ด๋ธ๋ณด๋ค ๋ ๋ง์ ์์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ง๋๊ฒ ์ผ๋ฐ์ ์ด๋ค.
์ฌ๋ฐ๋๊ฑด Embedded ํ์ ์ด Entity๋ฅผ ๊ฐ์ง ์๋ ์๋ค. (๊ทธ๋ฅ ์ฐ๋ ๊ฑฐ๋ ๋๊ฐ๋ค.)
// ์๋ฒ ๋๋ ํ์
์ฌ์ฉ
@Entity
public class Member {
@Id @GeneratedVAlue
private Long id;
private String name;
@Embedded // @Embedded ์๋ตํ๋๋ผ๋ JPA์์ ์์์ ์ฐพ์์ฃผ์ง๋ง, ์ฐ๋ ๊ฑธ ๊ถ์ฅํ๋ค.
private Period workPeriod; // ๊ทผ๋ฌด ๊ธฐ๊ฐ
@Embedded
private Address homeAddress; // ์ง ์ฃผ์
}
@Embeddable
public class Address {
@Column(name="city") // ๋งคํํ ์ปฌ๋ผ ์ ์ ๊ฐ๋ฅ
private String city;
private String street;
private String zipcode;
public boolean isMetropolitanCity (City city) {
// .. DB์ ์กด์ฌํ์ง์๋ ์๋ฏธ์๋ ์๋ก์ด ๊ฐ์ ๋ง๋ค ์ ์๋ค.
}
}
ํ๋ฒ ๋ ๋งํ์ง๋ง, Embedded ํ์ ์ ๊ฐ์ฒด์์๋ง ์กด์ฌํ ๋ฟ ํ ์ด๋ธ์๋ ์๋ฌด๋ฐ ์ํฅ์ด ์๋ค.
์ฐธ๊ณ ๋ก ์๋์ ๊ฐ์ด @Embedded ํ์ ์์ฒด๊ฐ null์ด๋ฉด, ๋ด๋ถ์๋ ์ ๋ถ null์ด ๋ค์ด๊ฐ๊ฒ ๋๋ค.
@Embedded
private Address homeAddress = null;
// Address ๊ฐ์ฒด์์ ์๋ ์นผ๋ผ ๊ฐ์ด ์ ๋ถ null๋ก ๋งคํ๋จ
โ ํ Entity์์ ๊ฐ์ ๊ฐ ํ์ ์ ์ฌ๋ฌ๊ฐ ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด?
Embedded ํ์ ์ ๊ฐ์ฒด์์๋ง ์ฌ์ฉํ๋ ๊ฒ์ผ ๋ฟ, ๋งคํํ๋ ํ ์ด๋ธ์ ๋ณํ๊ฐ ์๋ค๊ณ ํ๋ค.
๊ทธ๋์ ์๋์ ๊ฐ์ด ๊ฐ์ Embedded ํ์ ์ ์ฌ๋ฌ๋ฒ ์ฌ์ฉํ๋ฉด DB ์นผ๋ผ๋ช ์ด ์ค๋ณต๋์ด ๋งคํ์ด ๋ถ๊ฐ๋ฅํ๋ค. (์์ธ ๋ฐ์)
@Entity
public class Member {
@Embedded
private Address homeAddress;
@Embedded
private Address companyAddress;
}
์ด ๊ฒฝ์ฐ์๋ @AttributeOverrides๋ฅผ ์ด์ฉํด์ ์ง์ ํ ์ด๋ธ๊ณผ ์๋์ผ๋ก ๋งคํ์์ผ์ฃผ๋ฉด ๋๋ค.
@Embedded
@AttributeOverrides({
@AttributeOverride(name="city", column=@Column("WORK_CITY"))
@AttributeOverride(name="street", column=@Column("WORK_STREET")),
@AttributeOverride(name="zipcode", column=@Column("WORK_ZIPCODE")),
})
private Address homeAddress;
@Embedded
private Address companyAddress;
๐ ๊ฐ ํ์ ๊ณผ ๋ถ๋ณ ๊ฐ์ฒด(final)
๊ฐ ํ์ ์ ์ค์ ์ธ์คํด์ค (๊ฐ ๊ทธ ์์ฒด)๋ฅผ ๊ณต์ ํ๋๊ฑด ๋งค์ฐ ์ํํ๋ค.
๊ฐ ํ์ ์ ๋ฐ๋์ ๋ณต์ฌํด์ ์ฌ์ฉํด์ผํ๋ค.
๊ทธ๋ฌ๋ ๊ฐ์ฒด๋ ์ฐธ์กฐ๋ฅผ ์ ๋ฌํ๋๊ฑด ์ค์ํ๊ธฐ ์ฝ๋ค. ๊ณต์ ์ฐธ์กฐ ์์ฒด๋ฅผ ๋ง๋ ๋ฐฉ๋ฒ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
int a = 5;
int b = a; // ๊ฐ ๋ณต์ฌ
b = 4 // ์๋ฌด๋ฐ ๋ฌธ์ ์์.
Address a = new Address();
Address b = a; // ๐งจ ์ฐธ์กฐ๋ฅผ ์ ๋ฌํจ. ๊ฐ ๋ณต์ฌ๊ฐ ์๋
b.setCity("New") // ๐งจ a๋ ํจ๊ป ๋ณ๊ฒฝ๋จ!
์ด๋ ๊ฒ ์ธ๋ถ์ Side-Effect๋ก ๋ฐ์ํ๋ ๋ฒ๊ทธ๋ ์ฐพ๊ธฐ ์ ๋ง ์ด๋ ต๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด์๋ ๊ฐ ํ์ ์ ๋ถ๋ณ ๊ฐ์ฒด (immutable object)๋ก ์ค๊ณํด์ผ ํ๋ค.
์ฆ ์์ฑ์๋ก๋ง ๊ฐ์ ์ค์ ํ๊ณ , Setter๋ฅผ ๋ค ์์ ๋ฒ๋ ค์ผํ๋ค.
๐ ๊ฐ ํ์ - Collection
๊ฐ์ฒด์๋ ์ปฌ๋ ์ ์ด ์์ง๋ง, DB์๋ ์ปฌ๋ ์ ์ด๋ผ๋ ๊ฐ๋ ์ด ์๋ค. ์ปฌ๋ ์ ์ ์ ์ฅํ๊ธฐ ์ํ ๋ณ๋์ ํ ์ด๋ธ์ด ํ์ํ๋ค.
๋ํ Entity๊ฐ ์๋ [๊ฐ ํ์ ]์ PK๋ฅผ ๋ฐ๋ก ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์, ๋ชจ๋ ์นผ๋ผ์ ๋ฌถ์ด PK๋ก ์ฌ์ฉํด์ผํ๋ค.
null ์ ๋ ฅ์ ๋ง๊ณ ์ค๋ณต ์ ์ฅ์ ๋ง์์ผ ํ๊ธฐ ๋๋ฌธ.
@Entity์ ๊ฒฝ์ฐ 1:N ๊ด๊ณ๋ก ์ง์ ํด์ฃผ๋ฉด ๋์๋ค.
@Entity
public class Member{ ... }
@OneToMany(mappedBy="team")
private List<Member> members = nwe ArrayList<>();
๊ฐ ํ์ ์ ๊ฒฝ์ฐ @ElementCollection, @CollectionTable์ ์ฌ์ฉํ๋ฉด ๋๋ค.
@ElementCollection // ๊ธฐ๋ณธ ๊ฐ ํ์
@CollectionTable (name = "FAVORITE_FOOD", joinColumns = @JoinColumn(name="MEMBER_ID") )
private Set<String> favoriteFoods = new HashSet<>();
@ElementCollection // ์๋ฒ ๋๋ ๊ฐ ํ์
@CollectionTable (name = "FAVORITE_FOOD", joinColumns = @JoinColumn(name="MEMBER_ID") )
private List<Address> favoriteFoods = new ArrayList<>();
์ฐธ๊ณ ๋ก @ElementCollection(fetch = LAZY)๊ฐ ๊ธฐ๋ณธ๊ฐ์ด๋ค. ๊ฐ ํ์ ์ ์ฆ์๋ก๋ฉ์ผ๋ก ์ฐ๋ฉด ์ ๋ง ํฐ์ผ๋๋ค.
โ ๊ฐ ํ์ ์ปฌ๋ ์ ์ ํน์ง
- ๊ฐ ํ์ ์ Entity์ ๋ค๋ฅด๊ฒ ์๋ณ์ ๊ฐ๋ ์ด ์๋ค.
- ์๋ช ์ฃผ๊ธฐ๊ฐ Entity์ ๋ฌถ์ฌ์๋ค. ๋ฐ๋ก ์์ํ ํ ์ ์๊ณ ๋ถ๋ชจ Entity๋ฅผ persist()ํ๋ฉด ํจ๊ป ๋ฐ์๋๋ค.
- ๊ฐ ํ์
์ปฌ๋ ์
์ ์ผ๋ถ๊ฐ ๋ณ๊ฒฝ๋๋ฉด, ์์ ์ด ์๋๋ผ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ญ์ ํ๊ณ ๋ค์ ์ ์ฅํด์ผํ๋ค.
๊ทธ๋ ๊ฒ ํ์ง ์๊ณ ๊ฐํ์ ์ ๋ถ๋ณํ์ง ์๊ฒ ๋ง๋ค๊ณ ์์ ํ๋ค๋ฉด Side-effect๊ฐ ๋ฐ์ํ๋ค.
Member member = em.find(Member.class, 1L);
// ๐งจ SideEffect ๋ฐ์!! ๋ณ๊ฒฝ ์ถ์ ์ด ๋ถ๊ฐ๋ฅํ๋ค.
member.getHomeAddress().setCity("new city"); โ
// ์ด๋ ๊ฒ ๊ฐ ๊ฐ์ฒด๋ฅผ ์์ ์๋ก ๋ง๋ค์ด ๊ต์ฒดํด์ผํ๋ค. ์ค๋ณต๋๋๋ผ๋ ์ด์ฉ ์ ์๋ค.
member.setHomeAddress( new Address("new city","street","postcode") ); โญ
em.persist(member);
Member member = em.find(Member.class, 1L);
// ์ปฌ๋ ์
๋ ๋ง์ฐฌ๊ฐ์ง. ๊ฐ์ ์์ ํ๋ ๊ฐ๋
์ ์๋ค. ์๋ก์ด ๊ฐ ์ถ๊ฐ or ๊ธฐ์กด ๊ฐ ์ญ์ .
member.getFavoriteFoods().remove("์นํจ")
member.getFavoriteFoods().add("ํ์")
em.persist(member);
โ DB ์ฟผ๋ฆฌ๋ ๊ทธ๋ ๋ค. ์ ๋ฐ์ดํธ๋ฅผ ํ๋๊ฒ ์๋๋ผ ๊ต์ฒด๋ฅผ ํด๋ฒ๋ฆฐ๋ค.
@OrderColumn ์ ์ด์ฉํด์ ํ ์ด๋ธ ์ด๊ธฐํ๊ฐ ์๋ ์ ๋ฐ์ดํธ ์ฟผ๋ฆฌ๊ฐ ๋๊ฐ๊ฒ ํ ์๋ ์์ง๋ง.. null์ด ์ํํ๊ณ ๋ฒ๊ฑฐ๋กญ๋ค.
์ฐจ๋ผ๋ฆฌ Entity (AddressEntity)๋ก ๋ฐ๊ฟ์ ์ฌ์ฉํ์.
member.getAddresshistory().add( new Address( "old1", "city" ) );
member.getAddresshistory().remove( new Address( "old1", "city" ) );
member.getAddresshistory().add( new Address( "new1", "citty" ) );
// ๊ฒฐ๊ณผ์ ์ผ๋ก ๋จ์์๋ Address = ์ด 2๊ฐ
// ์ค์ ์ฟผ๋ฆฌ๋ ํ
์ด๋ธ์ ๋ ๋ ค๋ฒ๋ฆฌ๊ณ , ์๋ก์ด Address๋ฅผ 2๊ฐ ์ถ๊ฐํ๋ค.
โ ๊ฐ ํ์ ์ ๋ฐ๋์ equals()์ hashcode()๋ฅผ ์ ์ ํ๊ฒ ์ ์ํด์ฃผ์
JPA๋ ๊ฐ ํ์ ์ equals()์ hashcode() ๋ฅผ ์ด์ฉํด์ ํน์ ๊ฐ์ ์ฐพ์์ ์ญ์ ํ ์ ์๋ค.
member.getValues().remove(3) // ์ด๋ฐ ๊ฑด ๋น์ฐํ ๋๋ค.
member.getValues().add(4)
// ์ด๋ฐ ๊ฒ๋ ๊ฐ๋ฅํ๋ค. JPA๊ฐ equals์ hashcode ๋ฉ์๋๋ฅผ ์ด์ฉํด์ ๋น๊ต ํ ์ญ์ ํ๋ค.
member.getValues().remove( new Address("old1", "street", "10000") );
๊ทธ๋์ ์๋์ ๊ฐ์ด, ๊ฐ ํ์ ์ ๋ง๋ค ๋ equals์ hashcode๋ฅผ ์ ๋๋ก ๊ตฌํํ๋๋ก ํ์.
โก ๊ทธ๋์ ๊ตณ์ด ๊ฐ ํ์ Collection ์ ์ฌ์ฉํ๋ ๊ฒ ๋ณด๋ค Entity๋ก ์ ํํ๋๊ฒ ๋ ๋์ ์ ์๋ค.
์์์ ๋งํ Cascade ALL + Orphan Removal ์ ์ด์ฉํ๋ฉด Entity๋ฅผ ๊ฐ ํ์ ์ปฌ๋ ์ ์ฒ๋ผ ์ด์ฉํ ์ ์๋ค.
๐ ๊ฐ ํ์ ์, ์ ๋ง '๊ฐ'์ผ ๋์๋ง ์ฌ์ฉํ์.
โก ๊ฐ ํ์ Collection ์ ์ฌ์ฉํ๋ ๊ฒ ๋ณด๋ค @OneToMany Entity๋ก ์ ํํ๋๊ฒ ๋ ๋์ ์ ์๋ค.
์์์ ๋งํ Cascade ALL + Orphan Removal ์ ์ด์ฉํ๋ฉด Entity๋ฅผ ๊ฐ ํ์ ์ปฌ๋ ์ ์ฒ๋ผ ์ด์ฉํ ์ ์๋ค.
์๋ณ์๊ฐ ํ์ํ๊ณ ์ง์ํด์ ๋ณ๊ฒฝ์ ์ถ์ ํด์ผํ๋ค๋ฉด (๊ต์ฒด๊ฐ ์๋๋ผ ์ผ๋ถ ์์ ๋จ์ ์ถ์ ํด์ผ ํ๋ค๋ฉด) ๊ทธ๊ฑด ๊ฐ์ด ์๋ ์ํฐํฐ์์ ๋ช ์ฌํ์.
์ฐธ๊ณ ๋ก ๊ฐ ํ์ ์ ์ํฐํฐ ๋๋ฉ์ธ ๋ชจ๋ธ์์ ์๋์ ๊ฐ์ด ๊ทธ๋ฆด ์ ์๋ค.
'๐ฑBackend > JDBC & JPA' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
JPA ์ฑ๋ฅ ๊ฐ์ ํ (0) | 2022.01.22 |
---|---|
JPA 10 # ๊ฐ์ฒด ์ฟผ๋ฆฌ ์ธ์ด, JPQL (0) | 2021.11.16 |
JPA #8 ํ๋ก์์ ์ง์ฐ๋ก๋ฉ (join fetch) (0) | 2021.11.09 |
JPA #7 ๊ณ ๊ธ ๋งคํ (์์ ๊ด๊ณ) (0) | 2021.11.09 |
JPA #6 ๋ค์ํ ์ฐ๊ด๊ด๊ณ ๋งคํ (1:N, N:1, N:N) (0) | 2021.11.09 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev