Persistence Framework와 Mybatis

2023. 3. 24. 14:04WEB개발/TIL

반응형

JDBC

Java Database Connectivity

Java와 DB를 연결해주는 통로로, Java에서 데이터베이스에 접근할 수 있도록 도와주는 자바 API

연결 과정

 

 

Persistence Framework

영속성(Persistence)

: 프로그램이 종료되어도 데이터가 사라지지 않고 어딘가에 저장

Java에서는 JDBC를 통해 영속성을 부여할 수 있음

그러나, JDBC 프로그래밍은 번거로운 매핑 작업을 개발자가 직접 수행해야 한다는 문제가 존재함

이러한 문제를 해결하기 위한 것이 Persistence Framework

=> 개발자가 직접 번거로운 작업을 수행하지 않고 영속성 부여 가능

SQL MapperORM이 이에 해당함

 

 

SQL Mapper

Object와 SQL의 필드를 매핑해 데이터를 객체화하는 기술

객체와 테이블 간의 관계를 매핑하는 것이 아닌, SQL문의 수행 결과를 어떤 객체에 매핑할지 바인딩 하는 방법.

SQL문을 직접 작성해야 함.

ex) JDBCTemplate, MyBatis

 

MyBatis

SQL Mapper로써, JDBC로 처리하는 상당 부분의 코드와 파라미터 설정 및 결과 매핑을 대신함.

DB를 다루는 JDBC를 좀 더 편하고 깔끔하게 다루기 위한 DB 연동 프레임워크.

 

특징

1. 쉬운 접근성과 코드의 간결함.

  • JDBC의 모든 기능을 MyBatis에서 사용 가능
  • 복잡한 JDBC 코드를 걷어내 깔끔한 소스코드 유지 가능

 

2. SQL문과 프로그래밍 코드 분리.

  • SQL 쿼리문을 코드 내에 쓰지 않고, Mapper 파일에서 관리함으로써 코드와 SQL 쿼리를 분리
  • 따라서, SQL의 변경이 있을 때 다시 컴파일 할 필요 없음

 

3. 다양한 프로그래밍 언어로 구현 가능.

 

MyBatis 사용을 위한 설정

1. build.gradle 파일 내 dependencies에 코드 추가

* MyBatis를 사용하기 위해 dependency(라이브러리)를 추가하는 작업

implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
runtimeOnly 'com.mysql:mysql-connector-j'

2. ./src/main/resources/application.properties에 코드 추가

* application.properties 파일: Spring Boot가 애플리케이션을 구동할 때 자동으로 로딩하는 파일

* MyBatis 설정: DB명, DB사용자명, DB비밀번호, xml파일이 위치한 파일명은 각자 정보로 변경 필요

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/DB명?useUnicode=yes&characterEncoding=UTF-8&allowMultiQueries=true&serverTimezone=Asia/Seoul
spring.datasource.username=DB사용자명
spring.datasource.password=DB비밀번호

mybatis.type-aliases-package=com.spring.boot.mapper
mybatis.mapper-locations=xml파일이_위치한_파일명/*.xml

 

시작하기

1. 폴더구조 설정

Controller: 요청과 응답 처리

클라이언트의 요청을 받았을 때, 그 요청에 대한 실제 업무를 수행하는 Service를 호출

 

Domain: DB의 테이블 역할을 하는 클래스

즉, DB의 테이블과 매핑되며 Entity class라고도 불림

 

Dto: 데이터 저장 담당 클래스

Controller-Service와 같이 계층 간의 데이터 교환을 위해 사용

사용하는 이유? 로직의 효율성을 위해(데이터 전송 직렬화->캡슐화)

이미지1 참고

 

Mapper: Mapping 파일에 기재된 SQL 쿼리을 호출하기 위한 인터페이스

* Mybatis에서 Mapper 인터페이스 생성 시, 그에 관한 구현 클래스를 자동으로 생성됨.

 

Service: 각 도메인에서 요구되는 비지니스 로직을 처리하는 곳

 

resources/mybatis-mapper: SQL 쿼리문을 정의한 xml 파일이 있는 곳

이미지1

사진 출처: https://velog.io/@dasole1234/dTo-Controller-Service-Repository-%EB%9E%80

 

 

2. 코드 작성(Select문)

2.1. 서버(백) 부분

2.1.1. Domain > User.java

* Lombok 사용 (참고-https://palette77.tistory.com/41)

@Getter
@Setter
public class User {
    private int id;
    private String name;
    private String nickname;

}

2.1.2. Dto > UserDTO.java

@Getter
@Setter
public class UserDTO {
    private int id;
    private String name;
    private String nickname;
    private int no;
}

2.1.3. Controller

@Controller
public class MainController {

    @Autowired
    MainService mainService;

    @GetMapping("/")
    public String getUsers(Model model) {
        ArrayList<UserDTO> userList = (ArrayList<UserDTO>) mainService.getUserList(); // line9
        model.addAttribute("list",userList); // line10
        return "user"; // line11
    }

}
  • @Autowired: MainService 클래스를 Controller 클래스에서 사용할 수 있도록 의존성 주입
  • line9: MainService 클래스와 데이터 교환
  • line10: 클라이언트에게 list로 UserDTO 리스트 전달
  • line11: 해당 주소에서 보여줄 템플릿 파일명 리턴

 

2.1.4. Service

@Service
public class MainService {

    @Autowired
    private MainMapper mainMapper;

    public List<UserDTO> getUserList() {
        List<User> result = mainMapper.retrieveAll(); // line8
        List<UserDTO> users = new ArrayList<UserDTO>();  // line9

        for (int i=0; i<result.size(); i++) {  //line11
            UserDTO user = new UserDTO();
            user.setId(result.get(i).getId());
            user.setName(result.get(i).getName());
            user.setNickname(result.get(i).getNickname());
            user.setNo(i+1);

            users.add(user);
        }
        return users;  //line20
    }
}
  • line8: Mapper 인터페이스의 retrieveAll 메서드 리턴값(=DB에 받아온 데이터)
  • line9: UserDTO 객체 생성
  • line11: DB 값을 UserDTO로 매핑
  • line20: UserDTO가 담긴 list 리턴

 

2.1.5. Mapper

Mapper > MainMapper.java

@Mapper
public interface MainMapper {
    List<User> retrieveAll();
}

resources/mybatis-mapper > MainMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="sesac.apiPractice.Mapper.MainMapper">
    <select id="retrieveAll" resultType="sesac.apiPractice.Domain.User">
        SELECT user.* FROM user // line6
    </select>
</mapper>
  • namespace: Mapper 인터페이스가 담긴 패키지명+Mapper 인터페이스명 작
  • id: Mapper 인터페이스의 메서드명과 동일해야 함.
  • resultType: Mapper 인터페이스의 메서드 타입과 동일해야 함.
  • line6: 필요한 SQL 쿼리문 작성

 

2.2. 클라이언트 부분

<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <table>
        <tr>
            <th>번호</th>
            <th>ID</th>
            <th>이름</th>
            <th>닉네임</th>
        </tr>
        <tr th:each="user:${list}">
            <td th:text="${user.getNo()}">번호</td>
            <td th:text="${user.getId()}">ID</td>
            <td th:text="${user.getName()}">이름</td>
            <td th:text="${user.getNickname()}">닉네임</td>
        </tr>
    </table>
</body>
</html>

 

3. 결과 화면

결과 화면

 

 

 

 

반응형

'WEB개발 > TIL' 카테고리의 다른 글

ORM - JPA  (0) 2023.03.27
Lombok  (0) 2023.03.24
Spring에서 REST API  (0) 2023.03.22
Spring(DTO&VO, Bean, Annotation)  (0) 2023.03.21
REST API  (0) 2023.03.21