MyBatis-Spring项目
使用Spring IoC可以有效管理各类Java资源,达到即插即拔功能;通过AOP框架,数据库事务可以委托给Spring处理,消除很大一部分的事务代码,配合MyBatis的高灵活、可配置、可优化SQL等特性,完全可以构建高性能的大型网站。
MyBatis和Spring两大框架已经成了Java互联网技术主流框架组合,它们经受住了大数据量和大批量请求的考验,在互联网系统中得到了广泛的应用。使用MyBatis-Spring使得业务层和模型层得到了更好的分离,与此同时,在Spring环境中使用MyBatis也更加简单,节省了不少代码,甚至可以不用SqlSessionFactory、SqlSession等对象。因为MyBatis-Spring为我们封装了它们。
配置MyBatis-Spring项目需要这么几步:
•配置数据源。
•配置SqlSessionFactory。
•可以选择的配置有SqlSessionTemplate,在同时配置SqlSessionTemplate和SqlSessionFactory的情况下,优先采用SqlSessionTemplate。
•配置Mapper,可以配置单个Mapper,也可以通过扫描的方法生成Mapper,比较灵活。此时Spring IoC会生成对应接口的实例,这样就可以通过注入的方式来获取资源了。
配置SqlSessionFactoryBean
从MyBatis的介绍中,可以知道SqlSessionFactory是产生SqlSession的基础,因此配置SqlSessionFactory十分关键。在MyBatis-Spring项目中提供了SqlSessionFactoryBean去支持SqlSessionFactory的配置
几乎可以配置所有关于MyBatis的组件,并且它也提供了对应的setter方法让Spring设置它们,所以完全可以通过Spring IoC容器的规则去配置它们。由于使用了第三方的包,一般而言,我们更倾向于XML的配置。
代码清单:配置SqlSessionFactoryBean
<!--配置SqlSessionFactoryBean--> <bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:ssm/chapter12/sqlMapConfig.xml"/> </bean>
这里配置了SqlSesionFactoryBean,但是只是配置了数据源,然后引入一个MyBatis配置文件,当然如果你所配置的内容很简单,是可以完全不引入MyBatis配置文件的,只需要通过Spring IoC容器注入即可,但是一般而言,较为复杂的配置,笔者还是推荐你使用MyBatis的配置文件,这样的好处在于不至于使得SqlSessionFactoryBean的配置全部依赖于Spring提供的规则,导致配置的复杂性。
代码清单:MyBatis配置文件——sqlMapConfig.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="true"/> <!-- 允许 JDBC 支持生成的键。需要适当的驱动。如果设置为 true,则这个设置强制生成的键被使用,尽管一些驱动拒绝兼容但仍然有效(比如 Derby) --> <setting name="useGeneratedKeys" value="true"/> <!-- 配置默认的执行器。SIMPLE 执行器没有什么特别之处。REUSE 执行器重用预处理语句。BATCH 执行器重用语句和批量更新 --> <setting name="defaultExecutorType" value="REUSE"/> <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 设置超时时间,它决定驱动等待一个数据库响应的时间 --> <setting name="defaultStatementTimeout" value="25000"/> </settings> <!-- 别名配置 --> <typeAliases> <typeAlias alias="role" type="com.ssm.chapter12.pojo.Role"/> </typeAliases> <!-- 指定映射器路径 --> <mappers> <mapper resource="ssm/chapter12/mapper/RoleMapper.xml"/> </mappers> </configuration>
代码清单:RoleMapper.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.ssm.chapter12.mapper.RoleMapper"> <insert id="insertRole" useGeneratedKeys="true" keyProperty="id"> insert into t_role (role_name, note) values (#{roleName}, #{note}) </insert> <delete id="deleteRole" parameterType="long"> delete from t_role where id = #{id} </delete> <select id="getRole" parameterType="long" resultType="role"> select id, role_name as roleName, note from t_role where id = #{id} </select> <update id="updateRole" parameterType="role"> update t_role set role_name = #{roleName}, note = #{note} where id = #{id} </update> </mapper>
定义了一个命名空间(namespace)——com.ssm.chapter12.mapper.RoleMapper,并且提供了对角色的增、删、查、改方法。按照MyBatis的规则需要定义一个接口RoleMapper.java,才能够调用它
代码清单:RoleMapper.java
package com.ssm.chapter12.mapper; import com.ssm.chapter12.pojo.Role; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @Repository public interface RoleMapper { public int insertRole(Role role); public Role getRole(@Param("id") Long id); public int updateRole(Role role); public int deleteRole(@Param("id") Long id); }
到这里就完成了关于MyBatis框架的主要代码,由于RoleMapper是一个接口,而不是一个类,它没有办法产生实例,那么应该如何配置它呢
SqlSessionTemplate组件
严格来说,SqlSessionTemplate并不是一个必须配置的组件,但是它也存在一定的价值。首先,它是线程安全的类,也就是确保每个线程使用的SqlSession唯一且不互相冲突。其次,它提供了一系列的功能,比如增、删、查、改等常用功能
代码清单:配置SqlSessionTemplate
<!--配置SqlSessionTemplate--> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="SqlSessionFactory"/> <!-- <constructor-arg value="BATCH"/> --> </bean>
SqlSessionTemplate要通过带有参数的构造方法去创建对象,常用的参数是SqlSessionFactory和MyBatis执行器(Ex-ecutor)类型,取值范围是SIMPLE、REUSE、BATCH,这是我们之前论述过的执行器的3种类型。
代码清单:SqlSessionTemplate的应用
ApplicationContext ctx = new ClassPathXmlApplicationContext("ssm/chapter12/spring-cfg.xml");//ctx为Spring IoC容器 SqlSessionTemplate sqlSessionTemplate = ctx.getBean(SqlSessionTemplate.class); Role role = new Role(); role.setRoleName("role_name_sqlSessionTemplate"); role.setNote("note_sqlSessionTemplate"); sqlSessionTemplate.insert("com.ssm.chapter12.mapper.RoleMapper.insertRole", role); Long id = role.getId(); sqlSessionTemplate.selectOne("com.ssm.chapter12.mapper.RoleMapper.getRole", id); role.setNote("update_sqlSessionTemplate"); sqlSessionTemplate.update("com.ssm.chapter12.mapper.RoleMapper.updateRole", role); sqlSessionTemplate.delete("com.ssm.chapter12.mapper.RoleMapper.deleteRole", id);
当运行一个SqlSessionTemplate时,它就会重新获取一个新的SqlSession,也就是说每一个SqlSession-Template运行的时候会产生新的SqlSession,所以每一个方法都是独立的SqlSession,这意味着它是安全的线程。
关于SqlSessionTemplate,目前运用已经不多,正如代码清单一样所示,它需要使用字符串表明运行哪个SQL,字符串不包含业务含义,只是功能性代码,并不符合面向对象的规范。与此同时,使用字符串时,IDE无法检查代码逻辑的正确性,所以这样的用法渐渐被人们抛弃了。注意,SqlSessionTemplate允许配置执行器的类型,当同时配置SqlSessionFactory和SqlSessionTemplate的时候,SqlSessionTemplate的优先级大于SqlSessionFactory。
配置MapperFactoryBean
MyBatis的运行只需要提供类似于RoleMapper.java的接口,而无须提供一个实现类。通过学习MyBatis运行原理,可以知道它是由MyBatis体系创建的动态代理对象运行的,所以Spring也没有办法为其生成实现类。为了解决这个问题,MyBatis-Spring团队提供了一个MapperFactoryBean类作为中介,我们可以通过配置它来实现我们想要的Mapper。使用了Mapper接口编程方式可以有效地在你的逻辑代码中擦除SqlSessionTemplate,这样代码就按照面向对象的规范进行编写了,这是人们乐于采用的形式。
代码清单:配置RoleMapper对象
<!--配置RoleMapper对象--> <bean id="roleMapper" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!--RoleMapper接口将被扫描为Mapper --> <property name="mapperInterface" value="com.ssm.chapter12.mapper.RoleMapper"/> <property name="SqlSessionFactory" ref="SqlSessionFactory"/> <!--如果同时注入 sqlSessionTemplate 和 SqlSessionFactory,则只会启用sqlSessionTemplate --> <!-- <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/> --> </bean>
这里可以看到MapperFactoryBean存在3个属性可以配置,分别是mapperInterface、sqlSessionTemplate和SqlSessionFac-tory,其中:
•mapperInterface是映射器的接口。
•如果同时配置sqlSessionTemplate和SqlSessionFactory,那么它就会启用sqlSessionTemplate,而SqlSessionFac-tory作废。当我们配置这样的一个Bean,那么我们就可以使用下面的代码去获取映射器了。
RoleMapper roleMapper = ctx.getBean(RoleMapper.class);
配置MapperScannerConfigurer
这是一个通过扫描的形式进行配置Mapper的类,如果一个个去配置Mapper,显然工作量大,并且导致配置泛滥,有了它只需要给予一些简单的配置,它就能够生成大量的Mapper,从而减少工作量。首先我们需要知道它能够配置哪些属性,对于MapperScannerConfigurer它的主要配置项有以下几个:
•basePackage,指定让Spring自动扫描什么包,它会逐层深入扫描,如果遇到多个包可以使用半角逗号分隔。
•annotationClass,表示如果类被这个注解标识的时候,才进行扫描。对于开发而言,笔者建议使用这个方式进行注册对应的Mapper。在Spring中往往使用注解@Repository表示数据访问层(DAO,Data Access Object),所以本书的例子也是以此方式为主进行介绍的。
•SqlSessionFactoryBeanName,指定在Spring中定义SqlSessionFactory的Bean名称。如果sqlSessionTemplateBeanName被定义,那么它将失去作用。
•markerInterface,指定实现了什么接口就认为它是Mapper。我们需要提供一个公共的接口去标记。
代码清单:通过扫描的方式配置RoleMapper
<!--通过扫描的方式配置RoleMapper--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.ssm.chapter12.mapper"/> <property name="SqlSessionFactoryBeanName" value="SqlSessionFactory"/> <!--使用sqlSessionTemplateBeanName将覆盖SqlSessionFactoryBeanName的配置--> <!--<property name="sqlSessionTemplateBeanName" value="SqlSessionFactory"/>--> <!--指定标注才扫描成为Mapper--> <property name="annotationClass" value="org.springframework.stereotype.Repository"/> </bean>