JPA (2) - ์์์ฑ ์ปจํ ์คํธ
- EntityManagerFactory, EntityManager ํ์ต
- ์์์ฑ ์ปจํ ์คํธ
- ์ํฐํฐ์ ์๋ช ์ฃผ๊ธฐ
- ์์์ฑ ์ปจํ ์คํธ ํน์ง๊ณผ ์ค์ต
EntityManagerFactory, EntityManager
Entity
RDB์ table๊ณผ ๋งคํ๋๋ ๊ฐ์ฒด
EntityManagerFactory
Entity๋ฅผ ๊ด๋ฆฌํ๋ Entity Manager๋ฅผ ์์ฐํ๋ ๊ณต์ฅ.
: ๋น์ฉ์ด ๋น์ธ ํ๋๋ง ๋ง๋ค์ด์ง๊ณ Entity Manager๋ฅผ ์์ฐํ๋ factory์ฑ bean
: Thread safeํ๋ค. ํ๋์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ ๊ทผํด๋ ์์ ํ๋ค.
EntityManager
Entity๋ฅผ ์ ์ฅ, ์์ , ์ญ์ , ์กฐํ (CURD) ๋ฑ entity์ ๊ด๋ จ๋ ๋ชจ๋ ์ผ์ ์ฒ๋ฆฌํ๋ค.
: Thread Safeํ์ง ์๋ค. EntityManagerFactory์ ์ํด ์๋ก์ด manager๋ฅผ ์์ฑํด์ฃผ๋ฉฐ ๋จ์ผ ์ค๋ ๋๊ฐ ์ ๊ทผํ๋๋ก ์ฌ์ฉํ๋ค.
์ํฐํฐ ๋ฉ๋์ ๋ ํธ๋์ญ์ ์ commit์ด ์ผ์ด๋ ๋ ๊ทธ๋์์ผ connetion์ ๊ฐ์ ธ์ ์ฌ์ฉํ๋ค.
์์์ฑ ์ปจํ ์คํธ
์์์ฑ ์ปจํ ์คํธ
- JPA๋ฅผ ์ด์ฉํ๋๋ฐ ๊ฐ์ฅ ์ค์ํ ์์
- Entity๋ฅผ ์๊ตฌ ์ ์ฅํ๋ ํ๊ฒฝ
- Entity manager๋ ์ํฐํฐ๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ๋ณด๊ดํ๊ณ ๊ด๋ฆฌํ๋ค.
์์์ฑ ์ปจํ ์คํธ์ ํน์ง
- ์์์ฑ ์ปจํ ์คํธ ์ ์๋ณ์ ๊ฐ
: ์์์ฑ ์ปจํ ์คํธ ์์์ ๊ด๋ฆฌ๋๋ ์ํฐํฐ๋ ์๋ณ์ ๊ฐ์ ๋ฐ๋์ ๊ฐ์ ธ์ผํ๋ค.
: key-value๋ก ์ํฐํฐ๋ฅผ ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ (1์ฐจ ์บ์์์)
@Entity class์ @id ํ๋๋ฅผ ์ง์ ํ์ง ์์ผ๋ฉด ์ค๋ฅ๊ฐ ๋๋ ์ด์ .
- ์์์ฑ ์ปจํ ์คํธ์ ๋ฐ์ดํฐ ๋ฒ ์ด์ค ์ ์ฅ
: JPA๋ ํธ๋์ญ์ ์ ์ปค๋ฐํ๋ ์๊ฐ ์์์ฑ ์ปจํ ์คํธ์ ์๋ก ์ ์ฅ๋ ์ํฐํฐ๋ฅผ DB์ ๋ฐ์ํ๋ค.(FLUSH)
: ํ๋ฌ์๋ ์์์ฑ ์ปจํ ์คํธ์ ๋ณ๊ฒฝ ๋ด์ฉ์ DB์ ๋๊ธฐํํ๋ ์์ .
- ์์์ฑ ์ปจํ
์คํธ๊ฐ ์ํฐํฐ๋ฅผ ๊ด๋ฆฌํจ์ผ๋ก ์ป๋ ์ด์ .
- 1์ฐจ ์บ์
- ๋์ผ์ฑ ๋ณด์ฅ
- ํธ๋์ญ์ ์ ์ง์ํ๋ ์ฐ๊ธฐ ์ง์ฐ
- ๋ณ๊ฒฝ ๊ฐ์ง(dirty checking)
- ์ง์ฐ ๋ก๋ฉ
์ํฐํฐ ์๋ช ์ฃผ๊ธฐ
๋น์์ (new / transient) : ์์์ฑ ์ปจํ ์คํธ์ ์ ํ ๊ด๊ณ๊ฐ ์๋ ์ํ
// ๊ฐ์ฒด๊ฐ ์์์ฑ์ปจํ
์คํธ, ๋ฐ์ดํธ๋ฒ ์ด์ค์ ๋ฌด๊ดํ ์ํ์ด๋ค.
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
์์ (managed) : ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅ๋ ์ํ
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
// customer๊ฐ์ฒด๊ฐ ์์์ฑ ์ปจํ
์คํธ์์ ๊ด๋ฆฌ๋๋ค.
// em.find()๋ JPQL๋ฅผ ์ฌ์ฉํด์ ์กฐํํ ์ํฐํฐ๋ ์์ ์ํ.
em.persist(customer);
์ค์์ (detached) : ์์์ฑ ์ปจํ ์คํธ์ ์ ์ฅ๋์๋ค๊ฐ ๋ถ๋ฆฌ๋ ์ํ
// ์์์ํ์ customer๊ฐ์ฒด(์ํฐํฐ)๋ฅผ ์์์ฑ์ปจํ
์คํธ์์ ๋ถ๋ฆฌํ๋ค.
em.detach(customer);
// ์์์ํ์ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์์์ฑ์ปจํ
์คํธ์์ ๋ถ๋ฆฌํ๋ค.
em.clear()
// ์์์ฑ์ปจํ
์คํธ๋ฅผ ์ข
๋ฃํ๋ค.
em.close()
em.merge(customer);
์ญ์ (removed) : ์ญ์ ๋ ์ํ
// customer ์ํฐํฐ๋ฅผ ์์์ฑ์ปจํ
์คํธ์์ ๋ถ๋ฆฌํ๊ณ , DB์์๋ ์ญ์ ํ๋ค.
em.remove(customer)
์์์ฑ ์ปจํ ์คํธ๋ฅผ ํ๋ฌ์ํ๋ ๋ฐฉ๋ฒ 3๊ฐ์ง
- em.flush() ์ง์ ํธ์ถ.
- ํธ๋์ญ์ ์ปค๋ฐ์ ํ๋ฌ์๊ฐ ์๋ ํธ์ถ.
- JPQL (Java Persistence Query Langauge) ์ฟผ๋ฆฌ ์คํ์ ํ๋ฌ์๊ฐ ์๋ ํธ์ถ.
์์์ฑ ์ปจํ ์คํธ ์ดํดํ๊ธฐ
โ ์ ์ฅ
EntityManager em = emf.createEntityManager(); // 1)์ํฐํฐ ๋งค๋์ ์์ฑ
EntityTransaction transaction = em.getTransaction(); // 2)ํธ๋์ญ์
ํ๋
transaction.begin(); // 3)ํธ๋์ฐ์
begin
Customer customer = new Customer(); // 4-1)๋น์์
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer); // 4-2)์์ํ
transaction.commit(); // 5)ํธ๋์ญ์
commit
// ํธ๋์ญ์
์ด ์ปค๋ฐ์ด ๋๋ ์๊ฐ ์ฟผ๋ฆฌ๊ฐ ์ํ๋๋ค. flush DB์ ๋๊ธฐํ๊ฐ ๋๋ค.
์ฐ๊ธฐ ์ง์ฐ ์ ์ฅ์์ ์ฟผ๋ฆฌ ์ ์ฅ → 1์ฐจ ์บ์์ ์ ์ฅ → commit → DB์ ๋๊ธฐํ
โ ์กฐํ
→ 1์ฐจ ์บ์๋ฅผ ์ด์ฉํ ์กฐํ
@Test
void ์กฐํ_1์ฐจ์บ์_์ด์ฉ() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
Customer entity = em.find(Customer.class, 1L); // 1์ฐจ ์บ์์์ ์กฐํํ๋ค.
log.info("{} {}", entity.getFirstName(), entity.getLastName());
}
: 1์ฐจ ์บ์์ ์์ ๊ฒฝ์ฐ, DB์ ์ง์ํ์ง ์๊ณ 1์ฐจ ์บ์์์ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
→ DB๋ฅผ ์ด์ฉํ ์กฐํ
@Test
void ์กฐํ() {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(2L);
customer.setFirstName("guppy");
customer.setLastName("hong");
em.persist(customer);
transaction.commit();
em.clear(); //์์์ฑ ์ปจํ
์คํธ๋ฅผ ์ด๊ธฐํ ํ๋ค.
Customer entity = em.find(Customer.class, 2L); // DB ์์ ์กฐํํ๋ค. SELECT ...
log.info("{} {}", entity.getFirstName(), entity.getLastName());
em.find(Customer.class, 2L); // SELECT Query ์ํ๋์ง ์๋๋ค. 1์ฐจ์บ์ ์ฌ์ฉ
}
: 1์ฐจ ์บ์์ ์์ ๊ฒฝ์ฐ, DB์ ์ง์ํ์ฌ 1์ฐจ ์บ์์ ์ ์ฅํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํ
โ ์์
@Test
void ์์ () {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
// ์ํฐํฐ๋ฅผ ์์ํํํ, ์ปค๋ฐ์ํด์ flush()๋ฅผ ํตํด DB์ ์ ์ฅ.
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
entity.setFirstName("guppy");
entity.setLastName("hong");
// em.update(entity) ??!!
transacton.commit(); // flush -> UPDATE ...
}
dirty checking(๋ณ๊ฒฝ ๊ฐ์ง) ์ํ
→ ์ค๋ ์ท๊ณผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ์ฌํญ์ด ์๋์ง ํ์ธํ๋ค. ๋ณ๊ฒฝ ์ฌํญ์ด ์์ผ๋ฉด ์ฐ์ง ๊ธฐ์ฐ ์ ์ฅ์์์ update ์ฟผ๋ฆฌ๋ฅผ ๋ ๋ฆฐ๋ค.
: ์์์ฑ ์ปจํ ์คํธ์ ์ํฐํฐ๋ฅผ ๋ณด๊ดํ ๋, ์ต์ด ์ํ๋ฅผ ๋ณต์ฌํด์ ์ ์ฅํด๋๋๋ฐ ์ด๊ฒ์ ์ค๋ ์ท์ด๋ผ ํ๋ค.
: ํ๋ฌ์ ์์ ์ ์ค๋ ์ท๊ณผ ์ํฐํฐ๋ฅผ ๋น๊ตํ์ฌ ๋ณ๊ฒฝ ์ฌํญ์ ์ฐพ์, ๋ณ๊ฒฝ์ ์ํํ๋ค. ์ฆ, update๋ฅผ ์ง์ ํด์ค ํ์๊ฐ ์๋ค! (์์ ์ํ ์ํฐํฐ๋ง ์ ์ฉ๋จ)
: ๋ชจ๋ ํ๋๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์ซ๋ค๋ฉด ์ํฐํฐ๋ฅผ ์ ์ํ ๋ @DynamicUpdate ์ด๋ ธํ ์ด์ ์ ์ถ๊ฐํ๋ฉด ์ค์ ๋ก update ๋๋ ํ๋์ ๋ํด์๋ง update๋ฅผ ์ํํฉ๋๋ค.
โ ์ญ์
@Test
void ์ญ์ () {
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Customer customer = new Customer();
customer.setId(1L);
customer.setFirstName("honggu");
customer.setLastName("kang");
em.persist(customer);
transaction.commit();
transaction.begin();
Customer entity = em.find(Customer.class, 1L);
em.remove(entity);
transaction.commit(); // flush -> DELETE ..
}
์์์ฑ ์ปจํ์คํธ๋ฅผ ์ด์ฉํ๋ฉด JpaRepository ์ธํฐํ์ด์ค๋ ํ์์๋?
์ํฐํฐ ๋งคํ - ๋จ์ผ ์ํฐํฐ ๋งคํ
JPA ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋, ๊ธฐ๋ณธ ์์ฑ์๋ฅผ ์ฌ์ฉํ๋ค.
final ํ๋๋ ๋ชป๋ง๋๋?
๋ฐ์ดํฐ๋ฒ ์ด์ค ์คํค๋ง ์๋์์ฑ
spring:
h2:
console:
enabled: true
jpa:
generate-ddl: true
database: H2
show-sql: true
open-in-view: false
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
query.in_clause_parameter_padding: true
hbm2ddl:
auto: create-drop # ํ
์คํธ ์ฝ๋ ์์ฑํ ๋ ๋ง์ด ์ฌ์ฉ
์ด์ ํ๊ฒฝ์์๋ validation, none ์ ๋ง์ด ์ฌ์ฉํ๊ณ
create, create-drop, update ์ค์ ์ ์ค์ ํ ์ด๋ธ์ ์ํฅ์ ์ฃผ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ฐํ๊ฒฝ์ด๋ ํ ์คํธ ํ๊ฒฝ์์ ๋ง์ด ์ฌ์ฉํ๋ค.
DDL ์ต์
๊ตณ์ด ์ฌ์ฉํ์ง ์์๋ ๊ฐ๋ ์ฑ์ ์ํด ๋ช ์ํด ์ฃผ๋๊ฒ์ ๊ถ์ฅํ๋ค.
@Entity
@Table(name = "member")
@Getter
@Setter
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@Column(name = "name", nullable = false, length = 30)
private String name;
@Column(nullable = false, length = 30, unique = true)
private String nickName; // nick_name
private int age; // age
@Column(name = "addres", nullable = false) // ํฌ๊ธฐ๋ฅผ ์ ์ํ์ง์์ผ๋ฉด ๋ํดํธ ๊ฐ = 255
private String address;
@Column(name = "description", nullable = true)
private String description;
}
—-
# drop ์ต์
drop table if exists member CASCADE
drop sequence if exists hibernate_sequence
# create ์ต์
create sequence hibernate_sequence start with 1 increment by 1
create table member (id bigint not null, address varchar(255) not null, age integer not null, description varchar(255), name varchar(30) not null, nickName varchar(30) not null, primary key (id))
alter table member add constraint UK_1m3ighjll05v7njjxeopp823j unique (nickName)
๊ธฐ๋ณธํค ๋งคํ์ ๋ต @Id
- ์ง์ ํ ๋น
@Id
@Column(name = "id")
private Long id;
- SEQUENCE
: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค์์ ์๋ณ์ ๊ฐ์ ํ๋ํ ํ ์์ํ
: ORACLE, H2
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
- TABLE
: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํ์ค ์์ฑ์ฉ ํ ์ด๋ธ์์ ์๋ณ์ ๊ฐ์ ํ๋ํ ํ ์์ํ
- IDENTITY
: ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ํฐํฐ๋ฅผ ์ ์ฅํด์ ์๋ณ์ ๊ฐ์ ํ๋ํ ํ ์์ํ
: em.persist() ์์ ์ INSERT ์ฟผ๋ฆฌ๊ฐ ์ํ๋๊ณ ๊ทธ ๊ฒฐ๊ณผ๋ก key ๊ฐ์ ๊ฐ์ ธ์จ๋ค.
: MySQL (AUTO_INCREMENT)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
- AUTO
: ๋ฐ์ดํฐ ๋ฒ ์ด์ค ๋ฐฉ์ธ(dialect)์ ๋ฐ๋ผ์ ์๋์ผ๋ก ์ ๋ต์ ์ ํ. ์์ง์ ๋ง๋ ์ต์ ํ๋ ์ ๋ต์ด ์ฌ์ฉ๋๋ค.
๊ธฐํ ์ปฌ๋ผ๋งคํ
@Entity
@Table(name = "orders")
public class Order {
@Id
@Column(name = "id")
private String uuid;
@Column(name = "order_datetime", columnDefinition = "TIMESTAMP")
private LocalDateTime orderDatetime;
@Enumerated(EnumType.STRING)
private OrderStatus orderStatus;
@Lob // long text ํ์
private String memo;
}
๋ฐ์ดํฐ ์ค์ฌ ์ค๊ณ์ ๋ฌธ์ ์
@Test
void ์๋ชป๋_์ค๊ณ() {
Member member = new Member();
member.setName("youngji");
member.setAddress("์ธ์ง");
member.setAge(33);
member.setNickName("young");
member.setDescription("๋ฐฑ์ค๋ ๊ฐ๋ฐ์์์.");
EntityManager entityManager = emf.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
entityManager.persist(member);
Member memberEntity = entityManager.find(Member.class, 1L);
Order order = new Order();
order.setUuid(UUID.randomUUID().toString());
order.setOrderDatetime(LocalDateTime.now());
order.setOrderStatus(OPENED);
order.setMemo("๋ถ์ฌ์ ์ ํ์ฃผ์ธ์.");
order.setMemberId(memberEntity.getId()); // ์ธ๋ํค๋ฅผ ์ง์ ์ง์
entityManager.persist(order);
transaction.commit();
Order orderEntity = entityManager.find(Order.class, order.getUuid());
// FK ๋ฅผ ์ด์ฉํด ํ์ ๋ค์ ์กฐํ
Member orderMemberEntity = entityManager.find(Member.class, orderEntity.getMemberId());
// orderEntity.getMember()
// ๊ฐ์ฒด์ค์ฌ ์ค๊ณ๋ผ๋ฉด ๊ฐ์ฒด๊ทธ๋ํ ํ์์ ํด์ผํ์ง ์์๊น?
log.info("nick : {}", orderMemberEntity.getNickName());
}
order์์ ํ์ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๋๊ฒ ์๋๋ผ FK๋ก ๋ค์ ํ์ํ ์ด๋ธ์ ์กฐํํด์ผํ๋ค.
→ ์ค์ ์ํฐํฐ ๊ฐ์ฒด ์ฌ์ด์๋ ์๋ก๋ฅผ ์ฐธ์กฐํ์ง ์๋๋ค.
์ถ์ฒ - backend dev course ๊ฐํ๊ตฌ๋
'Back-end ๋ฐ๋ธ์ฝ์ค > week 08 TIL (Jpa)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[TIL] 221209 - JPA : REST-API, API ๋ฌธ์ํ (0) | 2022.12.20 |
---|---|
[TIL] 221208 - JPA : SpringDataJPA (0) | 2022.12.14 |
[TIL] 221207 - JPA : ์ฐ๊ด๊ด๊ณ ๋งคํ, ๊ณ ๊ธ ๋งคํ, ํ๋ก์ (0) | 2022.12.14 |
[TIL] 221205 - JPA : JPA ์๊ฐ (0) | 2022.12.07 |
๋๊ธ