Mybatis整合Spring
Mybatis提供了和Spring无缝对接的功能,它主要通过mybatis-spring-x.x.x.jar来实现。我们可以在 http://www.mybatis.org/spring/ 这个网址中找到对应的版本关系,然后下载对应版本即可。在Spring中,配置的方法较多,可以通过XML进行配置,也可以通过注解进行配置,但是通过XML配置的方式较为主流。
配置mybatis-spring分为以下几个部分:
- 配置数据源
- 配置SqlSessionFactory
- 配置SqlSessionTemplate(如需要)
- 配置Mapper
- 事务处理
配置数据源
我们这里就通过引入properties外置配置文件的方式来配置数据源,一个简单的properties文件:
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///ssm_crud
jdbc.user=root
jdbc.password=root
我们在spring的配置文件中引入这个文件,并配置四大参数即可,我这里用的是c3p0作为数据库连接池:
<!-- 引入jdbc.properties文件 --> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- 配置dataSource --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean>
当然我们也可以直接将四大参数写死,或者使用JNDI配置数据源都是可以的。
配置SqlSessionFactory
配置SqlSessionFactoryBean对象,我们还需要向其注入一个数据源和配置文件,使用classpath指定配置文件存在于类路径下:
<!--配置sqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"></property> <property name="dataSource" ref="dataSource"></property> <!-- 指定mybatis,mapper文件的位置 --> <property name="mapperLocations" value="classpath:mapper/*.xml"></property> </bean>
这样配置之后,我们就无需在mybatis配置文件中再配置environment节点信息了。严格来说,SqlSessionfactoryBean 已经可以通过Spring IOC配置了,我们完全可以在其内部配置很多原来的配置,如typeHandler,objectFactory,plugin,databaseIdProvider等等。但是建议还是将mybatis配置写到XML文件中,因为它方便管理,且可读性高。
configLocation属性指定Mybatis设置文件所在位置,dataSource属性指定数据源,mapperLocation属性指定Mapper映射XML文件所在的位置(所以在Mybatis设置文件中无需mapper元素)
Mybatis中使用的是SqlSessionFactoryBean,Hibernate中使用的是LocalSessionFactoryBean,JPA中使用的是LocalContainerEntityManagerFactoryBean
配置SqlSessionTemplate
SqlSessionTemplate(org.mybatis.spring.SqlSessionTemplate)是一个模版类,通过调用SqlSession来完成工作,所以在Mybatis-Spring项目中也是一个核心类。它有两个构建方式,一种是只有一个SqlSessionFactory作为参数;另一种是有两个参数的,一个是SqlSessionFactory,另一个是执行器类型,它是一个枚举类。
构建方法一,使用SqlSessionFactory参数构建
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> </bean>
构建方式二,使用两个参数构建
<!-- 配置一个可以执行批量(批处理)的sqlSessionTemplate --> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg> <constructor-arg name="executorType" value="BATCH"></constructor-arg> </bean>
这里executeType使用时BATCH,这是一个支持批处理的执行器,它的取值范围是:SIMPLE(默认,一个简易的执行器),RESULT(可重用预处理语句的执行器),BATCH(支持批处理和重用语句的执行器)
通过个SqlSessionTemplate配置就意味着Spring会把我们之前配置的SqlSessionFactory设置到SqlSessionTemplate中。如果我们同时配置了SqlSessionFactory和SqlSessionTemplate,那么系统就只会用使用SqlSessionTemplate去配置掉SqlSessionFactory。
在ibatis时代SqlSessionTemplate可以执行很多的功能,同样的在Mybatis中也是可以的。但是在目前的mybatis的编程中用的不多,因为我们完全可以使用映射器擦除它,这样更易于理解。除非是需要使用它完成定制的编程,不然不建议使用这种编程方式,原因有两个:
- SqlSessionTemplate是Mybatis的类,我们还需要使用id标记出调用的这条SQL,这对于编程来说是困难的,有侵入框架之嫌,可读性较差
- 我们在编写的时候无法保证调用SQL的id正确性,因为IDE无法验证id正确性
配置Mapper
在代码中,大部分场景都不建议使用SqlSessionTemplate或者SqlSession的方式,我们强烈建议使用Mapper接口的方式。
MapperFactoryBean
在Mybatis中,mapper只是一个接口,而不是一个实现类,它是有Mybatis通过动态代理的形式生成代理对象去运行的,所以Spring也没有办法为其生成实现类。为了解决这个问题,Mybatis-Spring团队提供了一个 MapperFactoryBean 类作为中介,配置MapperFactoryBean有3个参数,mapperInterface,SqlSessionfactory和SqlSessionTemplate。
- mapperInterface,用于定制接口,当我们的接口继承了配置的接口,那么Mybatis就认为它是一个Mapper
- SqlSessionfactory,当SqlSessionTemplate属性不被配置的时候,Mybatis-Spring才会去设置它
- SqlSessionTemplate,当它被配置的时候,SqlSessionFactory将被作废
<bean id="userDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!--userDao接口将被扫描为Mapper--> <property name="mapperInterface" value="cn.lynu.dao.UserDao"/> <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/> <!--如果同时注入SqlSessionTemplate和SqlSessionFactory,则只会启用sqlSessionTemplate--> <!-- property name="sqlSessionFactory" ref="sqlSessionFactory"/> --> </bean>
这样我们就可以使用这个接口进行编程了,它的作用等同于sqlSession.getMapper(UserDao.class),不过与Spring整合之后更加优雅。
MapperScannerConfigurer
一个复杂的系统存在许许多多的Dao,如果一个个配置,那么工作量会很大,不过Mybatis-Spring团队已经处理的这种场景,它采用自动扫描的形式来配置我们的映射器,这样我们就可以在很少的到代码情况下完成映射器的配置,提高效率。
我们采用的是MapperScannerConfigurer,它的部分常用属性如下:
- basePackage,指定Spring自动扫描什么包,它会逐层深入扫描
- annotationClass,表示如果这个类被这个注解标识的时候,才进行扫描
- sqlSessionFactoryBeanName,指定在Spring中定义的sqlSessionFactory的bean名称,如果它被定义,sqlSessionFactory 将不起作用
<!-- 配置mapper扫描器 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="cn.lynu.mapper"></property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean>
这样Spring上下文就会自动扫描cn.lynu.mapper这个包下的所有接口,并自动生成Mapper,而无需多余配置
配置事务
Mybatsi与Spring整合之后是使用Spring AOP去管理事务的,使用Spring AOP是相当简单的,它分为声明式事务和注解式事务,这里记录使用注解的方式配置事务
<!-- spring事务管理 --> <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 开启基于注解的事务 --> <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
在Mybatsi中使用的是DataSourceTransactionManager来作为事务管理器的,而Hibernate中我们使用HibernateTransactionManager 作为事务管理器,JPA中使用JpaTransactionManager作为事务管理器
这样我们在Service层使用@Transaction开启事务即可,这个注解可以作为类的注解,也可以细化请求的标在方法上