2025. 10. 20. 11:51ใJava/JPA
๐งฉ JPA ์ค์ต โข — ์ํฐํฐ ์๋ช ์ฃผ๊ธฐ (persist / find / merge / detach / remove)
์ด๋ฒ ์ค์ต์ JPA ์ํฐํฐ์ ์ ์ฒด ์๋ช
์ฃผ๊ธฐ๋ฅผ ๋ค๋ฃจ๋ฉฐ, ๊ฐ ๋ฉ์๋๊ฐ ์์์ฑ ์ปจํ
์คํธ์ ์ด๋ค ์ํฅ์ ์ฃผ๋์ง๋ฅผ ์ง์ ํ์ธํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก JPA์ ์๋ ์๋ฆฌ๋ฅผ ์์ ํ ์ดํดํ ์ ์๋ ํต์ฌ ๋จ๊ณ๋ค.

โถ ์ค์ต ๋ชฉํ
- persist() : ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ๋ฑ๋ก
- find() : DB ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ฒดํํ์ฌ 1์ฐจ ์บ์์ ์ ์ฅ
- merge() : ์กด์ฌํ๋ฉด update, ์์ผ๋ฉด insert ์ํ
- detach() : ์ํฐํฐ๋ฅผ ์์์ฑ ์ปจํ ์คํธ์์ ๋ถ๋ฆฌ
- remove() : ์ํฐํฐ ์ญ์ (1์ฐจ ์บ์ ๋ฐ DB ๋ฐ์)
โท ์ฝ๋ ๊ตฌ์ฑ
src/main/java/
โโ config/MyPersistenceUnitInfo.java
โโ entity/Employee.java
โโ Test.java
๐ Employee.java
package entity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
// @Table(name = "emp")
public class Employee {
@Id
// @Column(name="emp_id")
private int id;
private String name;
private String address;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", address=" + address + "]";
}
}
@Table / @Column ์ด๋ ธํ ์ด์ ๊ฐ๋จ ์ ๋ฆฌ
์ํฐํฐ ํด๋์ค์ ํ ์ด๋ธ๋ช ๊ณผ ์ปฌ๋ผ๋ช ์ DB์ ๋ค๋ฅด๊ฒ ์ง์ ํ๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ๋งคํ ์ด๋ ธํ ์ด์ ์ด๋ค.
๊ฐ๋จํ ์ด๋ ธํ ์ด์ ์ค์ต๋ ์งํํ๊ธฐ์ํด ๊ธฐ์กด์ employeeํ ์ด๋ธ๊ณผ ๋๊ฐ์ ํ ์ด๋ธ์ธ empํ ์ด๋ธ์ ๋ง๋ค์ด์ค๋ค ์ค์ต์งํํจ.
โ @Table
- ํด๋์ค ๋ ๋ฒจ์์ ์ฌ์ฉ๋๋ค.
- DB์ ์ค์ ํ ์ด๋ธ ์ด๋ฆ์ ์ง์ ํ๋ค.
@Entity
@Table(name = "emp") // ์ค์ ํ
์ด๋ธ๋ช
์ emp๋ก ์ง์
public class Employee { ... }
๐ ์๋ต ์ ํด๋์ค๋ช (Employee)์ด ํ ์ด๋ธ๋ช ์ผ๋ก ์๋ ๋งคํ๋๋ค.
โ @Column
- ํ๋(์์ฑ) ๋จ์๋ก ์ฌ์ฉ๋๋ค.
- DB์ ์ค์ ์ปฌ๋ผ ์ด๋ฆ, ๊ธธ์ด, ์ ์ฝ ์กฐ๊ฑด ๋ฑ์ ์ง์ ํ๋ค.
@Id
@Column(name = "emp_id", length = 10, nullable = false)
private int id;
์์ฑ ์ค๋ช ๐
| ์์ฑ๋ช | ์ค๋ช |
|---|---|
| name | DB ์ปฌ๋ผ๋ช ์ง์ |
| length | ๋ฌธ์์ด ์ปฌ๋ผ ๊ธธ์ด ์ง์ (๊ธฐ๋ณธ 255) |
| nullable | false๋ก ์ค์ ์ NOT NULL ์ ์ฝ์กฐ๊ฑด ์ ์ฉ |
| unique | ์ ๋ํฌ ์ ์ฝ์กฐ๊ฑด ์ค์ |
| insertable / updatable | SQL INSERT/UPDATE ์ ํฌํจ ์ฌ๋ถ ์ ์ด |
๐ก ์์
@Entity
@Table(name = "emp_table")
public class Employee {
@Id
@Column(name = "emp_id")
private int id;
@Column(name = "emp_name", length = 30)
private String name;
@Column(name = "emp_address", nullable = false)
private String a
๐ Test.java
import java.util.HashMap;
import config.MyPersistenceUnitInfo;
import entity.Employee;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import org.hibernate.jpa.HibernatePersistenceProvider;
public class Test {
public static void main(String[] args) {
EntityManagerFactory emf = new HibernatePersistenceProvider()
.createContainerEntityManagerFactory(new MyPersistenceUnitInfo(), new HashMap<>());
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
// #1. persist()
// ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์์ฑ ์ปจํ
์คํธ์ ๋ฑ๋ก (DB insert๋ commit ์์ )
// Employee e1 = new Employee();
// e1.setId(1);
// e1.setName("ํ๊ธธ๋");
// e1.setAddress("์์ธ");
// em.persist(e1);
// #2. find()
// Employee e = em.find(Employee.class, 1);
// System.out.println(e);
// e.setAddress("๋์ "); // update X
// System.out.println(e); // commit() ์์ ์ update O
// #3. merge()
// Employee e = new Employee();
// e.setId(2);
// e.setName("์ด๊ธธ๋");
// e.setAddress("๊ด์ฃผ");
// em.merge(e); // id=2๊ฐ ์์ผ๋ฉด insert
// Employee e2 = new Employee();
// e2.setId(2);
// e2.setName("์ด๊ธธ๋");
// e2.setAddress("๋ถ์ฐ");
// em.merge(e2); // id=2๊ฐ ์กด์ฌํ๋ฉด update
// #4. detach()
// Employee e = em.find(Employee.class, 2);
// System.out.println(e);
// em.detach(e); // ์์์ฑ ์ปจํ
์คํธ์์ ๋ถ๋ฆฌ
// e.setAddress("๊ฐ๋ฆ"); // update X (๋ ์ด์ ๊ด๋ฆฌ X)
// System.out.println(e);
// #5. remove()
// Employee e = em.find(Employee.class, 2);
// em.remove(e); // DB์์ ์ญ์ ๋จ (commit ์์ )
// ์๋๋ ์์ธ ๋ฐ์ ์์ (๋น์์ ๊ฐ์ฒด remove)
Employee e = new Employee();
e.setId(1);
em.remove(e); // IllegalArgumentException: detached instance
em.getTransaction().commit();
em.close();
}
}
โน ์ฃผ์ ๋ฉ์๋๋ณ ๋์ ์๋ฆฌ
โ โ persist()
- ์ ๊ฐ์ฒด๋ฅผ ์์์ฑ ์ปจํ ์คํธ(1์ฐจ ์บ์)์ ๋ฑ๋กํ๋ค.
- DB์ ์ฆ์ INSERT ๋์ง ์๊ณ , commit() ์์ ์ flush()๋๋ฉด์ SQL ์คํ.
โ โก find()
- DB ๋ฐ์ดํฐ๋ฅผ ์กฐํํด ๊ฐ์ฒด๋ก ๋ณํ ํ 1์ฐจ ์บ์์ ์ ์ฅํ๋ค.
- ๊ฐ์ ID๋ก ๋ค์ find()๋ฅผ ํธ์ถํ๋ฉด ์บ์์์ ๋ฐํ๋์ด DB ์กฐํ X.
โ โข merge()
- ๋น์์ ์ํ์ ์ํฐํฐ๋ฅผ ์์์ฑ ์ปจํ ์คํธ์ ๋ณํฉํ๋ค.
- DB์ ์กด์ฌํ์ง ์์ผ๋ฉด INSERT, ์กด์ฌํ๋ฉด UPDATE ์ํ.
- merge()๋ ํญ์ ์๋ก์ด ์์ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ค.
โ โฃ detach()
- ์์์ฑ ์ปจํ ์คํธ์์ ์ํฐํฐ๋ฅผ ๋ถ๋ฆฌ์ํจ๋ค.
- ์ดํ ํ๋ ๋ณ๊ฒฝ์ ๊ฐ์ง๋์ง ์์ผ๋ฉฐ, commit ์์ ์ update SQL X.
โ โค remove()
- ์ํฐํฐ๋ฅผ ์ญ์ ์ํ๋ก ํ์ํ๋ค.
- commit ์์ ์ DELETE SQL ์คํ.
- ๋น์์ ๊ฐ์ฒด๋ฅผ remove()ํ๋ฉด IllegalArgumentException ๋ฐ์.
โบ ์์ธ ์ํฉ ์ ๋ฆฌ
1๏ธโฃ ๋์ผํ ID๋ก persist() →
java.sql.SQLIntegrityConstraintViolationException: Duplicate entry '1' for key 'PRIMARY'
2๏ธโฃ ๋น์์ ๊ฐ์ฒด remove() →
java.lang.IllegalArgumentException: Removing a detached instance entity.Employee#1
โป ์ค์ต ํต์ฌ ์์ฝ
| ๋ฉ์๋ | ์ํ ๋ณํ | DB ๋ฐ์ ์์ | ๋น๊ณ |
|---|---|---|---|
| persist() | ๋น์์ → ์์ | commit() | 1์ฐจ ์บ์์ ๋ฑ๋ก |
| find() | DB → ์์ | ์ฆ์ (SELECT) | 1์ฐจ ์บ์ ์ฌ์ฌ์ฉ |
| merge() | ๋น์์ → ์์ | commit() | DB ์์ผ๋ฉด insert, ์์ผ๋ฉด update |
| detach() | ์์ → ์ค์์ | - | ๋ ์ด์ ๊ด๋ฆฌ๋์ง ์์ |
| remove() | ์์ → ์ญ์ | commit() | DELETE SQL ์คํ |
โผ ํต์ฌ ํ ์ค ์์ฝ
JPA์ ์ง์ง ๋ณธ์ง์ SQL ์คํ๊ธฐ๊ฐ ์๋๋ผ “์ํฐํฐ ์ํ ๊ด๋ฆฌ ์์คํ
”์ด๋ค.
persist()๋ก ๋ฑ๋ก๋๊ณ , find()๋ก ์กฐํ๋ ๊ฐ์ฒด๋ ๋ชจ๋ JPA๊ฐ ๊ฐ์ํ๊ณ ์๋ค.
commit() ์์ ์ flush() → ๋ณ๊ฒฝ ๊ฐ์ง → SQL ์์ฑ → DB ๋ฐ์์ด ์ผ์ด๋๋ค.
๐ ์ฉ์ด ์ ๋ฆฌ
| ์ฉ์ด | ์ค๋ช |
|---|---|
| ์์์ฑ ์ปจํ ์คํธ | ์ํฐํฐ๋ฅผ ์ ์ฅ·๊ด๋ฆฌํ๋ 1์ฐจ ์บ์ ๊ณต๊ฐ |
| ๋น์์ (Transient) | JPA๊ฐ ์์ง ๊ด๋ฆฌํ์ง ์๋ ๋จ์ ๊ฐ์ฒด |
| ์์ (Managed) | JPA๊ฐ ์ถ์ ์ค์ธ ๊ฐ์ฒด (persist, find ๊ฒฐ๊ณผ) |
| ์ค์์ (Detached) | ๋ ์ด์ ๊ด๋ฆฌ๋์ง ์๋ ๊ฐ์ฒด (detach ํ) |
| ์ญ์ (Removed) | commit ์ DELETE SQL ์คํ ์์ ์ํ |