danbibibi
article thumbnail
Published 2023. 4. 24. 21:31
MyBatis, MyBatis-Spring 설정 WEB/back-end

MyBatis

  • Java Object와 SQL문 사이의 자동 Mapping 기능을 지원하는 ORM Framework
  • SQL을 별도의 파일로 분리해서 관리 (유지 보수성 향상)
  • Object - SQL 사이의 parameter mapping 작업을 자동으로 해 줌
  • JDBC 코드와 수동으로 셋팅하는 파라미터와 결과 매핑을 제거 (코드의 중복과 작성 생략 가능)

 

https://mybatis.org/mybatis-3/ko/index.html

MyBatis – 마이바티스 3 | 소개

마이바티스는 무엇인가? 마이바티스는 개발자가 지정한 SQL, 저장프로시저 그리고 몇가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크이다. 마이바티스는 JDBC로 처리하는 상당부분의 코드와

mybatis.org

 
 

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
profile

danbibibi

@danbibibi

꿈을 꾸는 시간은 멈춰 있는 것이 아냐 두려워하지 마 멈추지 마 푸른 꿈속으로