6. 마이바티스 스프링 연동


  • 마이바티스의 데이터설정 일부를 생략, 스프링에 설정 추가

dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/springtx-3.1.xsd
  http://www.springframework.org/schema/context 
  http://www.springframework.org/schema/context/spring-context-3.1.xsd">

  <!-- 데이터소스 -->
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url" value="jdbc:mysql://localhost:3306/mybatis_example" />
    <property name="username" value="mybatis" />
    <property name="password" value="mybatis" />
    <property name="maxActive" value="20" />
    <property name="maxWait" value="6000" />
    <property name="poolPreparedStatements" value="true" />
    <property name="defaultAutoCommit" value="true" />
    <property name="initialSize" value="10" />
    <property name="maxIdle" value="20" />
    <property name="validationQuery" value="select 1" />
    <property name="testWhileIdle" value="true" />
    <property name="timeBetweenEvictionRunsMillis" value="7200000" />
  </bean>

  <!-- 트랜잭션 관리자 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>
  
  <!-- Annotation 을 사용한 트랜잭션 사용시 활성화 -->
  <tx:annotation-driven transaction-manager="transactionManager" />
  
  <!-- @Service, @Repository 애노테이션이 붙은 클래스를 빈으로 등록 -->
  <context:component-scan base-package="ldg.mybatis">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
  </context:component-scan>

  <!-- 마이바티스 설정 // -->
  <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="typeAliasesPackage" value="ldg.mybatis.model" />
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:/mybatis-config.xml" />
    <property name="mapperLocations">
      <array>
        <value>classpath*:/ldg/mybatis/repository/mapper/**/*.xml</value>
      </array>
    </property>
  </bean>
  <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
  </bean>
  <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="ldg.mybatis.repository" />
  </bean>

  <!-- // mybatis 설정 -->
</beans>

dataSource

  • dataSource id를 가진 bean은 데이터베이스 연결 정보를 가진 객체
  • 마이바티스와 스프링을 연동하면 데이터베이스 설정과 트랜잭션 처리는 스프링에서 관리
  • 스프링과 연동하면 마이바티스 설정에는 데이터베이스 연결정보 설정이 필요 없다
  • 데이터베이스 ConnectionPool을 위해 아파치 DBCP 프로젝트 구현체를 사용하도록 설정

context:component-scan

  • 스프링 빈을 매번 XML에 설정하지 않고 자동으로 검색해서 스프링 빈으로 등록 가능
  • 스프링 빈으로 등록되는 대상은 아래 어노테이션을 선언한 클래스가 대상
    • @Component
    • @Repository
    • @Service
    • @Controller

Repository

  • 마이바티스 기능을 사용하기 위해 Respoitory 클래스에서 SqlSessionTemplate 빈을 반드시 선언하고 사용해야한다
    • 스프링과 연동한 마이바티스 객체

예시

disppatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context" 
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:tx="http://www.springframework.org/schema/tx"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/tx 
  http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <!-- 데이터소스 -->
  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@yang-hp:1521:orcl" />
    <property name="username" value="scott" />
    <property name="password" value="tiger" />
  </bean>

  <!-- 트랜잭션 관리자 -->
  <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
  </bean>

  <!-- 마이바티스 설정 // -->
  <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="typeAliasesPackage" value="com.pd.model" />
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:/mybatis-config.xml" />
    <property name="mapperLocations">
      <array>
        <!-- <value>classpath:/com/mybatis/mapper/pd.xml</value> -->
        <value>classpath*:/com/mybatis/mapper/**/*.xml</value>
      </array>
    </property>
  </bean>
  <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactoryBean" />
  </bean>
  <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.mybatis.mapper" />
  </bean>
  
  <!-- Annotation 을 사용한 트랜잭션 사용시 활성화 -->
  <tx:annotation-driven transaction-manager="transactionManager" />
    <!-- @Controller, @Service, @Repository애노테이션이 붙은 클래스를 빈으로 등록 -->
    <context:component-scan base-package="com.pd“>
    </context:component-scan> ... </beans>

mybatis-config.xml

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

  <configuration>
    <!-- 마이바티스의 작동 규칙정의 -->
    <settings>
      <setting name="cacheEnabled" value="false"/>
      <setting name="useGeneratedKeys" value="false"/>
      <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
  </configuration>

pd.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="com.mybatis.mapper.pd">
    <insert id="pdInsert" parameterType="pdVo">
      <selectKey keyProperty="no" resultType="int" order="BEFORE">
        select pd_seq.nextval as no from dual
      </selectKey>
      insert into pd(no, pdname, price)
      values(#{no}, #{pdName}, #{price})
    </insert>
    <select id="pdList" resultType="pdVo">
      select * from pd order by no desc
    </select>
    <select id="pdDetail" parameterType="int" resultType="pdVo">
      select * from pd where no=#{no}
    </select>
    <update id="pdUpdate" parameterType="pdVo">
      update pd set pdname=#{pdName}, price=#{price}
      where no=#{no}
    </update>
    <delete id="pdDelete" parameterType="int">
      delete from pd where no=#{no}
    </delete>
  </mapper>

PdDAO

package com.pd.model;
import java.util.List;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class PdDAO{
  @Autowired
  private SqlSessionTemplate sqlSession;
  private final String namespace = "com.mybatis.mapper.pd";
  
  public int insertPd(PdVO pdVo){
    //pd 테이블에 insert하는 메서드
    int n = (int) sqlSession.insert(namespace + ".pdInsert", pdVo);
    return n;
  }
  public List<PdVO> selectAll(){
    //전체 글을 조회하는 메서드
    List<PdVO> alist
    = sqlSession.selectList(namespace + ".pdList");
    return alist;
  }
  public PdVO selectByNo(int no){
    //no에 해당하는 글 조회
    PdVO bean 
    = (PdVO) sqlSession.selectOne(namespace + ".pdDetail", no);
    return bean;
  }
  public int updatePd(PdVO bean){
    int n= sqlSession.update(namespace + ".pdUpdate", bean);
    return n;
  }
  public int deletePd(int no){
    //no에 해당하는 상품 삭제
    int n=sqlSession.delete(namespace + ".pdDelete", no);
    return n;
  }
}//class

PdService

package com.pd.model;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class PdService {
  @Autowired
  private PdDAO pdDao;

  @Transactional
  public int insertPd(PdVO pdVo){
    return pdDao.insertPd(pdVo);
  }
  public int updatePd(PdVO bean){
    return pdDao.updatePd(bean);
  }
  public List<PdVO> selectAll(){
    return pdDao.selectAll();
  }
.....
} 

Controller

package com.pd.controller;

@Controller
@RequestMapping("/pd/pdWrite.do")
public class PdWriteController {

  @Autowired
  private PdService pdService;

  @RequestMapping(method=RequestMethod.GET)
  public ModelAndView pdWriteGet(){
    ModelAndView mav = new ModelAndView();
    mav.setViewName("/pd/pdWrite");
    return mav;
  }
  @RequestMapping(method=RequestMethod.POST)
  public ModelAndView pdWritePost(@ModelAttribute("pdVo") PdVO pdVo){

    //1. 파라미터 읽어오기
    System.out.println("pdVo 파라미터 값 : " + pdVo);
    //2. db작업 - insert
    int n = pdService.insertPd(pdVo);
    System.out.println("상품 등록 여부, n="+n);
    //3. 결과, 뷰페이지 저장
    ModelAndView mav = new ModelAndView();
    //pdList.jsp 페이지로 redirect=> /pd/pdList.do로 redirect
    mav.setViewName("redirect:/pd/pdList.do");
    return mav;
  }
}//class