MyBatis에서 일대일 및 일대다 관계 처리를 위한 `<association>` 설정 사용법

<association>는 MyBatis에서 일대일 또는 일대다 관계를 처리하는 매핑 요소로, 쿼리 결과의 중첩 데이터를 Java 객체의 속성에 매핑하는 데 사용됩니다. 복잡한 데이터베이스 쿼리 결과를 중첩 객체로 매핑해야 할 때 특히 유용합니다.

1. 기능과 용도
  • 일대일 관계: 객체가 하나의 연결 객체를 포함할 때(예: Employee는 하나의 Department에만 속함) <association>를 사용하여 일대일 관계를 매핑합니다.
  • 일대다 관계: 객체가 여러 연결 객체를 포함할 때(예: Department에 여러 Employee가 소속됨) <association>를 사용하여 일대다 관계를 매핑합니다.
  • 다중 중첩 매핑: 여러 연결 객체가 포함된 쿼리 시 <association>가 쿼리 결과를 Java 객체에 자동으로 채워주어 복잡한 매핑 코드 작성을 방지합니다.
2. <association> 기본 사용법
  • property: Java 객체에서 연결 객체를 저장할 속성 이름
  • resultMap: 쿼리 결과의 필드를 해당 연결 객체에 매핑하는 방법을 지정하는 resultMap
  • columnPrefix: 데이터베이스 열에 접두사를 추가하여 열 이름 충돌을 방지
3. 예시 설명: 일대일 및 일대다 매핑

두 개의 엔티티인 EmployeeDepartment, 그리고 Company와 여러 Department를 가정하여 <association>를 사용한 일대일 및 일대다 매핑을 각각 설명합니다.

4. 예시 1: 일대일 관계 매핑

데이터 테이블 구조

데이터베이스에 employeesdepartments 두 개의 테이블이 있다고 가정합니다.

  • employees 테이블: 직원 정보 저장
emp_id emp_name dept_id
101 김철수 1
102 이영희 2
  • departments 테이블: 부서 정보 저장
dept_id dept_name location
1 개발부 서울
2 기획부 부산
1.1 Java 클래스 정의
// Employee.java
public class Employee {
    private int id;
    private String name;
    private Department department;  // 일대일 연결

    // getters and setters
}

// Department.java
public class Department {
    private int id;
    private String name;
    private String location;

    // getters and setters
}
1.2 resultMap 생성
<!-- Department resultMap -->
<resultMap id="departmentResultMap" type="com.example.Department">
    <result property="id" column="dept_id"/>
    <result property="name" column="dept_name"/>
    <result property="location" column="location"/>
</resultMap>

<!-- Employee resultMap -->
<resultMap id="employeeResultMap" type="com.example.Employee">
    <id property="id" column="emp_id"/>
    <result property="name" column="emp_name"/>
    <association property="department" resultMap="departmentResultMap"/>
</resultMap>
1.3 SQL 쿼리
<select id="findEmployeeWithDepartment" resultMap="employeeResultMap">
    SELECT e.emp_id, e.emp_name, d.dept_id, d.dept_name, d.location
    FROM employees e
    LEFT JOIN departments d ON e.dept_id = d.dept_id
    WHERE e.emp_id = #{empId}
</select>
1.4 결과 매핑

emp_id=101을 쿼리하면 다음과 같은 데이터가 반환됩니다:

emp_id emp_name dept_id dept_name location
101 김철수 1 개발부 서울

결과는 다음과 같이 매핑됩니다:

Employee employee = new Employee();
employee.setId(101);
employee.setName("김철수");

Department department = new Department();
department.setId(1);
department.setName("개발부");
department.setLocation("서울");

employee.setDepartment(department);

5. 예시 2: 일대다 관계 매핑

데이터 테이블 구조

두 개의 테이블: companiesdepartments가 있다고 가정합니다.

  • companies 테이블: 회사 정보 저장
comp_id comp_name
1001 삼성전자
1002 LG전자
  • departments 테이블: 부서 정보 저장
dept_id dept_name comp_id
1 연구개발 1001
2 마케팅 1001
3 인사 1002
2.1 Java 클래스 정의
// Department.java
public class Department {
    private int deptId;
    private String deptName;

    // getters and setters
}

// Company.java
public class Company {
    private int compId;
    private String compName;
    private List<Department> departments;  // 일대다 연결

    // getters and setters
}
2.2 resultMap 생성
<!-- Department resultMap -->
<resultMap id="departmentResultMap" type="com.example.Department">
    <result property="deptId" column="dept_id"/>
    <result property="deptName" column="dept_name"/>
</resultMap>

<!-- Company resultMap -->
<resultMap id="companyResultMap" type="com.example.Company">
    <result property="compId" column="comp_id"/>
    <result property="compName" column="comp_name"/>
    <association property="departments" resultMap="departmentResultMap"/>
</resultMap>
2.3 SQL 쿼리
<select id="findCompanyWithDepartments" resultMap="companyResultMap">
    SELECT c.comp_id, c.comp_name, d.dept_id, d.dept_name
    FROM companies c
    LEFT JOIN departments d ON c.comp_id = d.comp_id
</select>
2.4 결과 매핑

쿼리 결과:

comp_id comp_name dept_id dept_name
1001 삼성전자 1 연구개발
1001 삼성전자 2 마케팅
1002 LG전자 3 인사

다음과 같이 매핑됩니다:

List<Company> companies = new ArrayList<>();

// company 1
Company company1 = new Company();
company1.setCompId(1001);
company1.setCompName("삼성전자");

Department dept1 = new Department();
dept1.setDeptId(1);
dept1.setDeptName("연구개발");

Department dept2 = new Department();
dept2.setDeptId(2);
dept2.setDeptName("마케팅");

company1.setDepartments(Arrays.asList(dept1, dept2));

// company 2
Company company2 = new Company();
company2.setCompId(1002);
company2.setCompName("LG전자");

Department dept3 = new Department();
dept3.setDeptId(3);
dept3.setDeptName("인사");

company2.setDepartments(Arrays.asList(dept3));

// 리스트에 추가
companies.add(company1);
companies.add(company2);

6. 요약

  1. <association> 용도:
  • 일대일 관계: <association>를 사용하여 한 객체의 다른 객체 속성으로 매핑
  • 일대다 관계: <association>를 사용하여 여러 객체를 컬렉션 속성으로 매핑
  • 중첩 결과 매핑: 다중 중첩 쿼리 지원, 복잡한 쿼리 결과를 다중 중첩 Java 객체로 매핑
  1. 주요 속성:
  • property: 채울 Java 클래스 속성 지정
  • resultMap: 해당 연결 객체 매핑을 처리하는 resultMap 가리킴
  • columnPrefix: 데이터베이스 열 이름에 접두사 추가하여 열 이름 충돌 방지
  1. 쿼리 결과 매핑: <association>는 쿼리 반환 결과에 따라 중첩 객체를 Java 객체에 자동으로 채워주어 복잡한 쿼리 결과 처리를 단순화합니다.

적절히 <association>를 사용하면 일대일 및 일대다 객체 관계를 쉽게 처리할 수 있어 복잡한 결과 매핑 코드 작성을 피하고 코드의 유지보수성과 가독성을 향상시킬 수 있습니다.

태그: MyBatis ORM 데이터 매핑 일대일 관계 일대다 관계

6월 4일 18:13에 게시됨