MyBatis
- Java Object와 SQL문 사이의 자동 Mapping 기능을 지원하는 ORM Framework
- SQL을 별도의 파일로 분리해서 관리 (유지 보수성 향상)
- Object - SQL 사이의 parameter mapping 작업을 자동으로 해 줌
- JDBC 코드와 수동으로 셋팅하는 파라미터와 결과 매핑을 제거 (코드의 중복과 작성 생략 가능)
https://mybatis.org/mybatis-3/ko/index.html
MyBatis-Spring 연동
- MyBatis를 Standalone 형태로 사용하는 경우, SqlSessionFactory 객체를 직접 사용
- 스프링을 사용하는 경우, 스프링 컨테이너에 MyBatis 관련 빈을 등록하여 MyBatis를 사용
- 또한 스프링에서 제공하는 트랜잭션 기능을 사용하면 손쉽게 트랜잭션 처리
- MyBatis를 스프링과 연동하기 위해서는 MyBatis에서 제공하는 Spring 연동 라이브러리가 필요
<!-- pom.xml -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<!-- 3.x는 자바 11 이상을 사용 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.1.0</version>
</dependency>
1. DataSource 설정
- Spring을 사용하는 경우, 스프링에서 데이터 소스를 관리하므로 MyBatis 설정 파일에서는 일부 설정을 생략
- root-context.xml 파일에 DataSource를 설정 (아래 2가지 방식 존재)
- MyBatis와 Spring을 연동하면 데이터베이스 설정과 트랜잭션 처리는 Spring에서 관리
<!-- SDDS 방식 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
<property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/DBNAME?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</bean>
<!-- BasicDataSource 방식 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/DBNAME?serverTimezone=UTC"/>
<property name="username" value="root"/>
<property name="password" value="1234"/>
</bean>
💡 DataSource
: dataSource 아이디를 가진 빈으로 데이터베이스 연결정보를 가진 객체
DataSource를 사용하기 위해서는 pom.xml에 dependency를 추가해주어야 한다!
<!-- mysql-connector-j -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.32</version>
</dependency>
<!-- spring-jdbc for SDDS -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- commons-dbcp2 for BasicDataSource -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
2. Transaction 관리자 설정
- MyBatis는 JDBC를 그대로 사용하기 때문에 DataSourceTransactionManager 타입의 빈을 사용
- tx:annotation-driven 요소는 트랜잭션 관리 방법을 어노테이션으로 선언하도록 설정
- 스프링은 메소드나 클래스에 @Transactional 이 선언되어 있으면, AOP를 통해 트랜잭션을 처리
<!-- root-context.xml -->
<!-- 정상 수행 시 commit , 그렇지 않은 경우 rollback -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 어노테이션 기반 트랜잭션 설정 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
3. SqlSessionFactoryBean 설정
MyBatis 설정 파일을 바탕으로 SqlSessionFactory를 설정
- dataSource(데이터베이스 연결 설정 정보)가 반드시 필요
- mapperLocations : 매퍼에 관련된 자원의 위치
- typeAliasesPackage : resultType, parameterType 사용 시 bean 클래스명만 입력 가능
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations" value="classpath*:mappers/**/*.xml"/>
<property name="typeAliasesPackage" value="com.danbi.dto"/>
</bean>
<mybatis-spring:scan base-package="com.dnabi.model.repo"/>
4. mapping 파일 ( *.xml)
기존의 RepoImpl이 더 이상 필요하지 않다!
다음과 같이 SQL 문만 별도로 .xml 파일로 가지고 있을 수 있으며,
관련 JDBC 코드가 전부 사라져 간편하게 RepoImpl 파일을 대체할 수 있는 것이다!!
** 이렇게 해도 ServiceImpl에는 변화가 없다!!
DI를 통해 기존처럼 repo.insert() 같은 식으로 사용 가능하다!!
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.danbi.mvc.model.repo.EmpRepo">
<!-- parameterType 생략 가능 -->
<insert id="insert" parameterType="Emp">
insert into emp values (#{num}, #{name}, #{salary})
</insert>
<delete id="delete" parameterType="int">
delete from emp where num=#{num}
</delete>
<update id="update">
update emp set salary=#{salary} where num=#{num}
</update>
<!-- resultType은 생략 불가 -->
<select id="select" resultType="Emp">
select * from emp where num=#{num}
</select>
<!-- 하나가 리턴되든 여러개가 리턴되든 관계없음 (알아서 배열을 만들어서 반환) -->
<select id="search" resultType="Emp">
SELECT * FROM emp
</select>
</mapper>
💡#{}
- 값에 ' '가 자동으로 붙음
- PreparedStatement 통해 악의적인 쿼리주입을 예방할 수 있음
- 보완차원에서 유리
- 주로 사용자의 입력을 전달할때 사용
💡${}
- ' '가 자동으로 붙지않음
- Statement 방식으로 파라미터가 출력되어 전달
- 의도적인 쿼리주입을 막을 수 없음
- SQL injection 보안 위험 발생 가능
- 주로 table명, column명 전달시 사용
동적 Query
if
- EL 처럼 test 속성에 조건을 넣어 사용
- title이 null인 경우 state='ACTIVE' 까지만 반영된 쿼리 수행
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>
</select>
choose , when, otherwise
- if문과 사용하는 방식 동일
- 조건에 맞는 한가지 경우만 확인 가능
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
trim, where, set
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
foreach
- 값이 배열, List 등으로 넘어왔을 때 처리
- EL 문법과 다름
- collection : 배열, List 객체
- index : 인덱스 변수 이름 지정
- item : 변수 이름 지정
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
<where>
<foreach item="item" index="index" collection="list"
open="ID in (" separator="," close=")" nullable="true">
#{item}
</foreach>
</where>
</select>
'WEB > back-end' 카테고리의 다른 글
web.xml, servlet-context.xml, root-context.xml (0) | 2023.04.25 |
---|---|
Spring-MyBatis 실습 (0) | 2023.04.24 |
Spring File Upload (Apache Commons FileUpload) (1) | 2023.04.24 |
Spring MVC 실습 (0) | 2023.04.24 |
Interceptor (0) | 2023.04.22 |