Spring和Mybatis框架整合

来源:互联网 发布:网络命令的使用 编辑:程序博客网 时间:2024/05/21 10:29

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);

实现:

@Overridepublic 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点而言,成立的前提条件就是不能捕获异常,只能抛出异常

原创粉丝点击