- camel case를 snake case로 바꾸기 위해 persistence.xml 파일 수정
- 아래 내용 추가
<property name="hibernate.physical_naming_strategy" value="org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy"/>
JPA 연관관계
- 데이터베이스 테이블에서 FK가 있는 쪽이 연관관계의 주체!
@ManyToOne // - fetch type : EAGER
@JoinColumn(name = "dept_id")
private Department department;
JPA 연관관계 Annotation
Annotation |
fetch type |
OneToOne |
EAGER |
OneToMany |
EAGER |
ManyToOne |
LAZY |
- fetch type - LAZY : 지연 로딩
- fetch type - EAGER : 즉시 로딩
단방향 연관관계 (ManyToOne)
Employee.java
package domain;
import javax.persistence.*;
@Entity
@Table(name = "employee")
public class Employee {
@Id
@Column(length = 6)
private String empId;
@Column(length = 10, nullable = false)
private String empName;
// @OneToOne // - fetch type : EAGER
// @OneToMany // - fetch type : LAZY
@ManyToOne // - fetch type : EAGER
@JoinColumn(name = "dept_id")
private Department department;
private String joinDate;
private long salary;
public Employee() {
}
public Employee(String empId, String empName, Department department, String joinDate, long salary) {
this.empId = empId;
this.empName = empName;
this.department = department;
this.joinDate = joinDate;
this.salary = salary;
}
public String getEmpId() {
return empId;
}
public void setEmpId(String empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public String getJoinDate() {
return joinDate;
}
public void setJoinDate(String joinDate) {
this.joinDate = joinDate;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
}
Department.java
package domain;
import javax.persistence.*;
@Entity
@Table(name = "dept")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int deptId;
@Column(name = "dept_name", length = 10, nullable = false)
private String deptName;
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
}
Emp_Dept_Test.java
package jpajava;
import domain.Department;
import domain.Employee;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class Emp_Dept_Test {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpatest");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
System.out.println("Transaction START!");
try {
Department dept = new Department();
dept.setDeptName("HR"); // 비영속 상태
em.persist(dept); // 영속 상태, 즉시 쓰기
System.out.println("dept 생성");
Employee employee = new Employee();
employee.setEmpId("202401");
employee.setEmpName("홍길동");
employee.setDepartment(dept);
employee.setSalary(100); // 비영속 상태
em.persist(employee); // 영속 상태, 지연 쓰기
System.out.println("employee 생성 #1");
employee = new Employee();
employee.setEmpId("202402");
employee.setEmpName("김연아");
employee.setDepartment(dept);
employee.setSalary(200); // 비영속 상태
em.persist(employee); // 영속 상태, 지연 쓰기
System.out.println("employee 생성 #2");
System.out.println("commit 전");
tx.commit(); // 이 때 employee가 insert됨
System.out.println("commit 후");
} catch (Exception e) {
tx.rollback();
System.out.println("[Error] : " + e.getMessage());
} finally {
System.out.println("Transaction COMPLETED!");
}
}
}
실행 결과
양방향 연관관계 (ManyToOne, OneToMany)
Department.java
package domain;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Table(name = "dept")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int deptId;
@Column(length = 10, nullable = false)
private String deptName;
@OneToMany(mappedBy = "department")
List<Employee> employeeList = new ArrayList<>();
public int getDeptId() {
return deptId;
}
public void setDeptId(int deptId) {
this.deptId = deptId;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public List<Employee> getEmployeeList() {
return employeeList;
}
}
- mappedBy 속성 추가
- Employee 엔터티의 department 필드를 통해 매핑된다는 의미
- Employee 엔터티가 연관관계의 주체가 되어 데이터베이스의 FK 관리 권한을 가지게 됨
- mappedBy 속성이 있는 클래스에서는 Getter만 구현한다. 값을 설정하는건 연관관계의 주체가 할 것이므로 Setter는 구현할 필요가 없음