Java의 MyBatis 프레임워크와 Spring 프레임워크의 통합 활용 상세 정보

17650 단어 JavaMyBatisSpring
mybatis를 단독으로 사용하는 것은 많은 제한이 있다. (예를 들어 여러 세션을 뛰어넘는 업무를 실현할 수 없다.) 그리고 많은 업무 시스템은 원래spring을 사용하여 관리하는 업무이기 때문에 mybatis는spring과 통합하여 사용하는 것이 가장 좋다.
버전 요구 사항
프로젝트
버전
다운로드 주소
설명
mybatis
3.0 이상
https://github.com/mybatis/mybatis-3/releases
 
spring
3.0 이상
http://projects.spring.io/spring-framework/
 
mybatis-spring
1.0 이상
https://github.com/mybatis/spring/releases
 
spring 트랜잭션 구성

<!--   --> 
<context:component-scan base-package="com.xxx.service" /> 
 
<!--   --> 
<jee:jndi-lookup id="jndiDataSource" jndi-name="java:comp/env/jdbc/datasource" /> 
 
<!--   --> 
<bean id="txManager" 
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
  <property name="dataSource" ref="jndiDataSource" /> 
</bean> 
<!--  aop --> 
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true"/> 

단일 통합

<!--  mybatis --> 
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
  <property name="dataSource" ref="jndiDataSource" /> 
  <property name="configLocation" value="classpath:/mybatis/mybatis-config.xml" /> 
  <!--   --> 
  <property name="typeAliasesPackage" value="com.xxx.dto" /> 
</bean> 
 
<!-- dao bean(  )--> 
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
  <property name="mapperInterface" value="com.xxx.dao.UserDao" /> 
  <property name="sqlSessionFactory" ref="sqlSessionFactory" /> 
</bean> 

우리는 어떻게 사용하는지 알아야 할 뿐만 아니라, 왜 이렇게 사용하는지 더욱 알아야 한다.
SqlSessionFactoryBean은 공장 bean으로 그 역할은 설정 (데이터 원본, 별명 등) 을 해석하는 것이다.
Mapper Factory Bean은 공장 bean입니다. 스프링 용기에 공장 bean은 특수한 용도가 있습니다. 스프링이 공장 bean을 다른 bean에 주입할 때 공장 bean 자체가 아니라 bean의 get Object 방법을 사용합니다.다음은 이 get Objec 방법이 무엇을 했는지 살펴보자.

public T getObject() throws Exception { 
 return getSqlSession().getMapper(this.mapperInterface); 
} 
보시면 아시겠지만 이 방법은 저희가 이전에 Mybatis를 단독으로 사용했던 방식과 똑같습니다. 모두 먼저 Sqlsession 대상을 얻은 다음에 Sqlsession에서 Mapper 대상을 가져옵니다. (다시 한 번 Mapper는 프록시 대상입니다. 이 프록시는 mapper Interface 인터페이스이고 이 인터페이스는 사용자가 제공하는dao 인터페이스입니다.)자연히 최종적으로 업무층에 주입되는 것이 바로 이 Mapper 대상이다.
실제 프로젝트는 일반적으로 하나의 Dao가 아니라 여러 개의 Dao가 있다면 위의 설정에 따라 순서대로 설정하면 된다.
대량 업데이트 사용 방법
앞에서 말한 바와 같이 마퍼의 대상을 업무층에 주입하는 방법을 설명했습니다. 마퍼의 행위는 설정에 의존합니다. 마퍼는 기본적으로 하나의 업데이트 (즉 Executor Type은 BATCH가 아닌 SIMPLE) 를 사용합니다. 물론 우리는 마퍼의 프로필을 수정해서 기본 행동을 수정할 수 있습니다. 그러나 만약에 우리가 어떤 마퍼나 몇 개의 마퍼가 대량 업데이트를 사용하도록 하려면 할 수 없습니다.이때 우리는 템플릿 기술을 사용해야 한다.

<!-- mybatis  --> 
lt;bean id="sqlSessionTemplateSimple" class="org.mybatis.spring.SqlSessionTemplate">   
<constructor-arg index="0" ref="sqlSessionFactory" /> 
<!--  --> 
<constructor-arg index="1" value="SIMPLE"/> 
</bean> 
   
<!-- mybatis  --> 
lt;bean id="sqlSessionTemplateBatch" class="org.mybatis.spring.SqlSessionTemplate">   
<constructor-arg index="0" ref="sqlSessionFactory" /> 
<!--  --> 
<constructor-arg index="1" value="BATCH"/> 
</bean> 

여기서 필자는 두 개의 템플릿 대상을 정의했는데 하나는 하나의 업데이트를 사용하고 하나는 대량의 업데이트를 사용한다.템플릿이 생기면 우리는 마퍼의 행동 방식을 바꿀 수 있다.

<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> 
  <property name="mapperInterface" value="com.xxx.dao.UserDao" /> 
  <property name="sqlSessionTemplate" ref=" sqlSessionTemplateBatch " /> 
</bean> 
 
이전 절의 마퍼 설정이 다른 것은 여기는 sqlSessionFactory 속성을 설정할 필요가 없고 sqlSessionTemplate(sqlSessionFactory 속성은 템플릿에 이미 설정되어 있음)만 설정할 수 있다는 것이다.
자동 스캔을 통해 마퍼의 설정을 간소화하다
앞의 장에서 보듯이 우리의dao는 프로필에 하나하나 설정해야 한다. 만약에dao가 많으면 프로필이 매우 커서 관리하기가 비교적 고통스럽다.다행히 mybatis팀도 이 점을 깨달았다. 그들은 스프링이 제공하는 자동 스캐닝 기능을 이용하여 자동 스캐닝 도구류를 봉인했다. 이렇게 하면 우리는 이 기능을 사용하여 설정을 간소화할 수 있다.

<!--  mapper bean( ) --> 
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
  <property name="basePackage" value="com.xxx.dao" /> 
  <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplateSimple" /> 
  <property name="markerInterface" value="com.xxx.dao.SimpleDao" /> 
</bean> 
    
<!--  mapper bean( ) --> 
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
  <property name="basePackage" value="com.xxx.dao" /> 
  <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplateBatch" /> 
  <property name="markerInterface" value="com.xxx.dao.BatchDao" /> 
</bean> 

Mapper Scanner Configurer 자체가 관련된spring의 기술은 더 이상 말하지 않겠습니다. 흥미롭고 스프링의 원리에 대해 비교적 잘 알고 있는 것은 그 원본을 볼 수 있습니다.우리는 그것의 세 가지 속성을 중점적으로 보았다.
  • 베이스 패키지: 스캐너가 스캐닝을 시작하는 기본 패키지 이름, 플러그인 스캐닝 지원;
  • sqlSessionTemplateBeanName: 앞에서 언급한 템플릿 bean의 이름;
  • markerInterface: 인터페이스의 필터를 바탕으로 이 인터페이스를 실현하는dao는 스캐너에 의해 스캔되고 베이스 패키지와 작용합니다..
  • 인터페이스 필터링 외에 메모 필터링도 사용할 수 있습니다.
    
    <!--  mapper bean( ) --> 
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> 
      <property name="basePackage" value="com.xxx.dao" /> 
      <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplateBatch" /> 
      <property name="annotationClass" value="com.xxx.dao.BatchAnnotation" /> 
    </bean> 
    
    annotationClass: 이 주석을 설정한 dao가 스캐너에 의해 스캔됩니다. 베이스 패키지와 같은 역할을 합니다.
    주의해야 할 것은 두 개의 필터 조건이 하나만 어울릴 수 있다는 것이다.
    예: 트랜잭션 관리
    엔티티 클래스 정의: Emp.java
    
    package com.lixing.scm.entity;
    
    public class Emp {
     private String id;
     private String name;
     private String sex;
     private int age;
     private String phone;
     public String getId() {
      return id;
     }
     public void setId(String id) {
      this.id = id;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public String getSex() {
      return sex;
     }
     public void setSex(String sex) {
      this.sex = sex;
     }
     public int getAge() {
      return age;
     }
     public void setAge(int age) {
      this.age = age;
     }
     public String getPhone() {
      return phone;
     }
     public void setPhone(String phone) {
      this.phone = phone;
     }
    }
    
    
    엔티티 내 작업 인터페이스 정의: EmpMapper.java
    
    package com.lixing.scm.test.mapper;
    
    import java.util.List;
    import java.util.Map;
    
    import com.lixing.scm.entity.Emp;
    
    public interface EmpMapper {
     void insertEmp(Emp emp);
     List<Emp> getAllEmp();
     Emp getById(String id);
     void deleteEmp(String id);
     void updateEmp(Map<String,Object> map);
    }
    
    
    솔리드 클래스 작업 인터페이스의 매핑 파일 정의:EmpMapper.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.lixing.scm.test.mapper.EmpMapper"> 
     <parameterMap type="com.lixing.scm.entity.Emp" id="parameterMapEmp">
      <parameter property="id"/>
      <parameter property="name"/>
      <parameter property="sex"/>
      <parameter property="age"/>
      <parameter property="phone"/>
     </parameterMap>
     
     <resultMap type="com.lixing.scm.entity.Emp" id="resultMapEmp">
      <result property="id" column="id"/>
      <result property="name" column="name"/>
      <result property="sex" column="sex"/>
      <result property="age" column="age"/>
      <result property="phone" column="phone"/>
     </resultMap>
     
     <insert id="insertEmp" parameterMap="parameterMapEmp">
      INSERT INTO emp(id,name,sex,age,phone)
      VALUES(?,?,?,?,?)
     </insert>
     <select id="getAllEmp"  resultMap="resultMapEmp">
      SELECT * FROM emp
     </select>
     <select id="getById" parameterType="String" resultMap="resultMapEmp">
      SELECT * FROM emp
      WHERE id=#{value}
     </select>
     <delete id="deleteEmp" parameterType="String">
      DELETE FROM emp 
      WHERE id=#{value}
     </delete>
     <update id="updateEmp" parameterType="java.util.Map">
      UPDATE emp
      SET name=#{name},sex=#{sex},age=#{age},phone=#{phone}
      WHERE id=#{id}
     </update>
    </mapper>
    Spring3.0.6 :applicationContext.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:aop="http://www.springframework.org/schema/aop"
     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/context
         http://www.springframework.org/schema/context/spring-context-3.0.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
         http://www.springframework.org/schema/aop 
         http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
    
     <!--  -->
     <context:annotation-config />
     <context:component-scan base-package="com.lixing.scm.test.*" />
    
    
     <!-- jdbc.propertis Directory -->
     <bean
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="locations" value="classpath:jdbc.properties" />
     </bean>
    
     <bean id="MyDataSource" destroy-method="close"
      class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
     </bean>
    
     <!-- SqlSessionFactory -->
     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="MyDataSource" />
     </bean>
     <!-- ScanMapperFiles -->
     <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
      <property name="basePackage" value="com.lixing.scm.test.mapper" />
     </bean>
    
    
    
     <!-- ================================ =================================================  -->
     <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   
         <property name="dataSource" ref="MyDataSource"></property>
      </bean>   
     
     <tx:advice id="userTxAdvice" transaction-manager="transactionManager">
      <tx:attributes>
       <tx:method name="delete*" propagation="REQUIRED" read-only="false" 
                  rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/>
       <tx:method name="insert*" propagation="REQUIRED" read-only="false" 
                  rollback-for="java.lang.RuntimeException" />
       <tx:method name="update*" propagation="REQUIRED" read-only="false" 
                  rollback-for="java.lang.Exception" />
       
       <tx:method name="find*" propagation="SUPPORTS"/>
       <tx:method name="get*" propagation="SUPPORTS"/>
       <tx:method name="select*" propagation="SUPPORTS"/>
      </tx:attributes>
     </tx:advice>
     
     <aop:config>  
      <aop:pointcut id="pc" expression="execution(public * com.lixing.scm.test.service.*.*(..))" /> <!-- Service -->
      <aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" />
     </aop:config>
     
     
     <!--  Bean-->
     <bean id="empDao" class="com.lixing.scm.test.dao.impl.EmpDaoImpl"
      autowire="byName" /> 
     <bean id="empService" class="com.lixing.scm.test.service.impl.EmpServiceImpl"  autowire="byName"/>
    </beans>
    
    
    DAO 커넥터: EmpDAO.java
    
    package com.lixing.scm.test.dao;
    
    import java.util.List;
    import java.util.Map;
    
    import com.lixing.scm.entity.Emp;
    
    public interface EmpDao {
     void insertEmp(Emp emp);
     List<Emp> getAllEmp();
     Emp getById(String id);
     void deleteEmp(String id);
     void updateEmp(Map<String, Object> map);
    }
    
    
    DAO 인터페이스 구현 클래스: EmpDaoImpl.java
    
    package com.lixing.scm.test.dao.impl;
    
    import java.util.List;
    import java.util.Map;
    
    import com.lixing.scm.entity.Emp;
    import com.lixing.scm.test.dao.EmpDao;
    import com.lixing.scm.test.mapper.EmpMapper;
    
    public class EmpDaoImpl implements EmpDao {
     private EmpMapper empMapper;  // empMapper
       // empMapper  Spring    // 
     @Override
     public void insertEmp(Emp emp) {
      this.empMapper.insertEmp(emp);
      throw new RuntimeException("Error");  // RuntimeException    // 
     }
    
     @Override
     public void deleteEmp(String id) {
      this.empMapper.deleteEmp(id);
     }
    
     @Override
     public List<Emp> getAllEmp() {
      return this.empMapper.getAllEmp();
     }
    
     @Override
     public Emp getById(String id) {
      return this.empMapper.getById(id);
     }
    
     @Override
     public void updateEmp(Map<String, Object> map) {
      this.empMapper.updateEmp(map);
     }
    
     
     public EmpMapper getEmpMapper() {
      return empMapper;
     }
    
     public void setEmpMapper(EmpMapper empMapper) {
      this.empMapper = empMapper;
     }
    }
    
    
    서비스 레이어 인터페이스: EmpService.java
    
    package com.lixing.scm.test.service;
    
    import com.lixing.scm.entity.Emp;
    
    public interface EmpService {
     void insertEmp(Emp emp);
    }
    
    
    서비스 레이어 인터페이스 구현 클래스: EmpServiceImpl.java
    
    package com.lixing.scm.test.service.impl;
    
    import com.lixing.scm.entity.Emp;
    import com.lixing.scm.test.dao.EmpDao;
    import com.lixing.scm.test.service.EmpService;
    
    public class EmpServiceImpl implements EmpService {
     private EmpDao empDao;
    
     @Override
     public void insertEmp(Emp emp) {
      empDao.insertEmp(emp);
    
     }
    
     public EmpDao getEmpDao() {
      return empDao;
     }
    
     public void setEmpDao(EmpDao empDao) {
      this.empDao = empDao;
     }
    }
    
    
    테스트 클래스: TestEmp Service.java
    
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import com.lixing.scm.entity.Emp;
    import com.lixing.scm.test.service.EmpService;
    
    
    public class TestEmpService {
     @Test
     public void testTrasaction(){
      Emp emp=new Emp();
      emp.setId("00000003");
      emp.setName(" ");
      emp.setAge(50);
      emp.setSex(" ");
      emp.setPhone("566666");
      
      ApplicationContext ctx=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
      EmpService service=ctx.getBean(EmpService.class);
      service.insertEmp(emp);
     }
    }
    

    좋은 웹페이지 즐겨찾기