Spring和Mybatis框架整合

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_30322803/article/details/78517369

Spring和MyBatis框架的整合


Spring和MyBatis环境整合

    在实际开发中,Mybatis框架和Spring框架是一起使用的,Spring框架一个重要的作用就是Bean的管理,所有的对象都可以交给Spring进行管理。Mybatis框架访问数据库的核心类是SqlSessionFactory,通过SqlSessionFactory获得SqlSession对象,然后操作sql语句访问数据库。Mybatis框架和Spring框架整合的基本出发点就在于将SqlSessionFactory这个对象交给Spring管理。本文将详细的描述Mybatis框架和Spring框架的整合过程。

    一丶导入必要Jar包。

    1.Spring框架所需要的包

    2.Mybatis框架所需要的所有包

    3.Mybatis和Spring整合的中间jar包

    4.数据库驱动jar包

    5.数据源jar包

       

           图1 Myabtis和Spring框架整合所需要的jar包

     二丶书写Spring的配置文件

    整合Spring和Mybatis框架时,Spring框架的applicationContext.xml配置文件最开始应该包括以下几个部分:

    1.DataSource,数据源交给Spring配置管理,在Mybatis配置文件中不需要配置DataSouce了。

    2.在Spring中开启注解扫描

    3. 开启事务注解以及在Spring中配置事务管理器,整合后事务由Spring管理,不交给Mybatis管理

    4.在Spring中配置SqlSessionFactory对象,SqlSessionFactory对象交给Spring管理。

   applicationContext.xml配置文件的内容如下:

<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
    http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
   http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-4.3.xsd
    http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
   
    <!-- 配置数据源 -->
    <bean id="dataSource"
            class="org.apache.commons.dbcp2.BasicDataSource">
        <!--数据库驱动 -->
        <property name="driverClassName"value="com.mysql.jdbc.Driver" />
        <!--连接数据库的url -->
        <property name="url"value="jdbc:mysql://localhost:3306/mybatis" />
        <!--连接数据库的用户名 -->
        <property name="username"value="root" />
        <!--连接数据库的密码 -->
        <property name="password"value="root" />
        <!--最大连接数 -->
        <property name="maxTotal"value="30" />
        <!--最大空闲连接  -->
        <property name="maxIdle"value="10" />
        <!--初始化连接数  -->
        <property name="initialSize"value="5" />
    </bean>
    <!-- 事务管理器,依赖于数据源 -->
    <bean id="transactionManager"class=
     "org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource"ref="dataSource" />
    </bean>   
    <!--开启事务注解 -->
    <tx:annotation-driventransaction-manager="transactionManager"/>
    <!-- 开启扫描 -->
    <context:component-scan base-package="com.bupt"/>
    <!--配置MyBatis工厂-->
    <bean id="sqlSessionFactory"
            class="org.mybatis.spring.SqlSessionFactoryBean">
         <!--注入数据源 -->
         <property name="dataSource"ref="dataSource" />
         <!--指定核心配置文件位置 -->
       <propertyname="configLocation" value="classpath:mybatis-config.xml"/>
   </bean>
</beans>

三丶MyBatis配置文件书写

1.MyBatis首先书写MyBatis的主配置文件MyBatis_config.xml

<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEconfiguration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--配置Mapper的位置 -->
    <mappers>
    </mappers>
</configuration>

可以发现MyBatis中Enviroments元素不需要配置了,因为DataSource交给Spring管理了,在MyBatis中之需要包含Mapper.xml映射文件即可

              传统Dao方式的开发整合之CRUD

经过以上三个步骤,Spring和Mybatis的整合环境基本已经搭建完成,接下来用一个具体实例子介绍如何利用传统Dao方式在整合环境下完成对数据库的访问。通过一个对Customer表进行CRUD的例子来介绍访问流程

一丶Customer表设计:

          图1 Customer表设计

    二丶Customer实体类设计

在com.bupt.bean包下,创建Customer类

  public classCustomer {
    publicint id;
    publicString name;
    publicString telePhone;
    publicString job;
    publicString idcard;
    publicint getId() {
       returnid;
    }
    publicvoid setId(int id) {
       this.id= id;
    }
    publicString getName() {
       returnname;
    }
    publicvoid setName(String name) {
       this.name= name;
    }
    publicString getTelePhone() {
       returntelePhone;
    }
    publicvoid setTelePhone(StringtelePhone) {
       this.telePhone= telePhone;
    }
    publicString getJob() {
       returnjob;
    }
    publicvoid setJob(String job) {
       this.job= job;
    }
    publicString getIdcard() {
       returnidcard;
    }
    publicvoid setIdcard(String idcard) {
       this.idcard= idcard;
    }
    @Override
    publicString toString() {
       return"Customer [id=" + id + ", name=" + name + ",telePhone=" + telePhone + ", job=" + job + ", idcard="
              + idcard + "]";
    }
}

三丶创建Mybatis下的映射文件,完成sql语句设计

在com.bupt.mapper包下创建一个CustomerMapper.xml映射文件:

<?xmlversion="1.0" encoding="UTF-8"?>
<!DOCTYPEmapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mappernamespace="com.bupt.mapper.CustomerMapper">
    <select id="queryCustomerByID"parameterType="int" resultType="com.bupt.bean.Customer">
           select * from customer where id=#{id}
    </select>
</mapper>

创建完CustomerMapper.xml映射文件后,需要将CustomerMapper映射文件添加到MyBatis主配置文件,Mybatis_config.xml文件中。

四丶在com.bupt.dao包下创建一个接口CustomerDao,和CustomerDaoImpl类

CustomerDao类

 public interface CustomerDao {
    publicCustomer queryCustomerByID(intid);
}

CustomerDaoImpl类

public class CustomerDaoImpl extends SqlSessionDaoSupport implements CustomerDao{
    @Override
    public Customer queryCustomerByID(int id) {
       Customercustomer = this.getSqlSession().
                            selectOne("com.bupt.mapper.CustomerMapper"+".queryCustomerByID",2);
       return customer;
    }
}

CustomerDaoImpl类必须继承SqlSessionDaoSupporty类,this.getSession方法是SqlSessionDaoSupport中的方法,用来获取sqlSession。

五丶在Spring的applicationContext配置文件配置Customer类

<!--配置Customer对象,并且向其中注入sqlSessionFactory对象-->
   <bean id="customerDao" class="com.bupt.dao.CustomerDaoImpl">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"></property>
   </bean>

继承sqlSessionDaoSupport类后,必须向其中注入 sqlSessionFactoryBean。

六丶测试代码实现,引入了junit4这个测试框架

@Test
   public void queryTest(){
       ApplicationContext context = newClassPathXmlApplicationContext("applicationContext.xml");
       CustomerDao customerDao = (CustomerDao)context.getBean("customerDao");
       Customer customer =customerDao.queryCustomerByID(2);
       System.out.println(customer);
    }

七丶测试结果:

              图2测试结果

传统Dao方式的开发整合之事务

    上节中借助一个查询的例子,简单的介绍了传统Dao方式整合下,如何访问数据库,本节中介绍Spring和MyBatis整合后如何开启事务

    最开始的时候,我们在Spring的appilcationContext配置文件中,配置了事务管理器以及打开了注解开关,这两个条件已经完全满足了Spring对事务控制的要求,我们可以利用基于注解的方式去配置事务。事务的配置一般设置到Service层。通过一个插入Customer的例子来验证事务操作的有效性

一丶在CustomerMapper文件中添加如下insert元素:

<insert id="insertCustomer"parameterType="com.bupt.bean.Customer">
           insert intocustomer(id,telePhone,name,job,idcard)
           value(#{id},#{telePhone},#{name},#{job},#{idcard})
</insert>

二丶在CustomerDao和CustomerDaoimple类中分别添加如下声明以及实现:

声明:

public void insertCustomer(Customer customer);

实现:

@Override
public void insertCustomer(Customer customer) {
    // TODO Auto-generated method stub
    this.getSqlSession().
             insert("com.bupt.mapper.CustomerMapper"+".insertCustomer",customer);
}

三丶在CustomerService方法中添加事务

public classCustomerService {
    CustomerDao customerDao;
    publicCustomerDao getCustomerDao() {
       returncustomerDao;
    }
    publicvoid setCustomerDao(CustomerDao customerDao){
       this.customerDao= customerDao;
    }
    @Test
    publicvoid queryTest(){
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       CustomerDao customerDao = (CustomerDao) context.getBean("customerDao");
       Customer customer = customerDao.queryCustomerByID(2);
       System.out.println(customer);
    }
    //
   @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    publicvoid insertTest(){
       Customer customer = new Customer();
       customer.id=4;
       customer.name="tu";
       customer.job="student";
       customer.telePhone="1314";
       customer.idcard="1";
       customerDao.insertCustomer(customer);
       int i=1/0;
    }
}

在insertTest方法中,用inti=1/0来模拟异常,假如开启事务的话,insert语句不会插入成功。假如未开启事务的话insert语句将插入成功。

四丶在Spring配置文件applicationContext.xml中配置CustomerService

<bean id="customerService"class="com.bupt.service.CustomerService">
        <property name="customerDao"ref="customerDao"></property>
   </bean>

五丶测试案例

   public class CustomerTest {
    publicstatic void main(String []args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       CustomerService customerService =(CustomerService) context.getBean("customerService");
       customerService.insertTest();
    }
}

六丶测试结果

              

              图1 执行前数据库状态

      

图2 执行后数据库状态

    发现执行前后数据库表中的记录并未改变,因为抛出除零异常,事务发生了回滚。

七丶Spring有关事务的重要补充

在CustomerService方法中,我们对insertTest方法声明了事务。Spring默认对RuntimeException异常进行回滚,而int i=1/0除零异常是RuntimeException,所以回滚生效。假如我们抛出IOException,可以看看Spring事务管理的结果

@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    publicvoid insertTest(){
       Customer customer = new Customer();
       customer.id=4;
       customer.name="tu";
       customer.job="student";
       customer.telePhone="1314";
       customer.idcard="1";
       customerDao.insertCustomer(customer);
       try{
           new IOException();
       }
       catch(Exceptione){
           e.printStackTrace();
       }
}

在这种情况下调试结果:

  图3 抛出IOException异常执行状态

可以发现在这种情况下,事务并没有发生回滚。插入语句执行成功。

有人可能会提出这个问题,是不是对IOException异常进行了捕获,所以事务无法回滚,因此去掉try catch,改成throws,代码修改如下,观察执行结果。

@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    publicvoid insertTest() throwsException{
       Customer customer = new Customer();
       customer.id=4;
       customer.name="tu";
       customer.job="student";
       customer.telePhone="1314";
       customer.idcard="1";
       customerDao.insertCustomer(customer);
       new IOException();
    }


图4 抛出IOException异常并且未捕获,执行状态

    可以观察到,事务依旧没有发生回滚,那是是不是throwsException方法无用呢?不是的,对于非RuntimeException异常而言,不进去捕获,抛出异常,是Spring事务回滚必须的操作,只是我们准备工作尚不充分而已。

    修改Transactionnal配置,添加rollbackFor选项,修改如下:

@Transactional(rollbackFor=IOException.class,propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
    publicvoid insertTest()throws Exception{
       Customer customer = new Customer();
       customer.id=4;
       customer.name="tu";
       customer.job="student";
       customer.telePhone="1314";
       customer.idcard="1";
       customerDao.insertCustomer(customer);
       thrownew IOException();
    }

可以看到,在Transactional注释中,我们添加了rollbackFor选项,指定了强制回滚的IOException异常。此时在测试运行发现事务回滚了。

       

       图5 非Runtime异常,正确事务配置运行结果

总上所述,对于Spring和Mybatis事务操作做如下总结:

1.Spring和Mybatis整合后,事务交给Spring管理,Spring配置事务注解开关,以及事务管理器

2.Spring默认是对RuntimeException异常发生事务回滚

3.对于特定的异常,如果要求Spring发生事务回滚,需要配置rollbackFor选项。

4.对于第3点而言,成立的前提条件就是不能捕获异常,只能抛出异常

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页