Spring集成MyBatis使用
前面复习MyBatis时,发现在测试时,需要手动创建sqlSessionFactory,Spring将帮忙自动创建sqlSessionFactory,并且将自动扫描Mapper映射器
(1)集成步骤
step1 导包: spring-webmvc, mybatis, mybatis-spring, dbcp, ojdbc, spring-jdbc, junit, mysql相关等
<dependencies> <!--导入junit测试包--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <classifier>sources</classifier> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <classifier>javadoc</classifier> </dependency> <!-- 导入数据库包 --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.1.0</version> </dependency> <!-- 导入mybatis的包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.0</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> <classifier>sources</classifier> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> <classifier>javadoc</classifier> </dependency> <!-- 针对mysql的导包 --> <dependency> <groupId>org.wisdom-framework</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.34_1</version> </dependency> <!-- 导入spring-webmvc的jar包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.3.RELEASE</version> <classifier>sources</classifier> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.3.RELEASE</version> <classifier>javadoc</classifier> </dependency> <!-- 针对spring JDBC导包 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.3.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.3.RELEASE</version> <classifier>sources</classifier> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.3.RELEASE</version> <classifier>javadoc</classifier> </dependency> <!-- 关键:导入mybatis-spring --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> <classifier>sources</classifier> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.2</version> <classifier>javadoc</classifier> </dependency> </dependencies>
注意:导包可能出现版本不兼容的问题,可以参考博客建议,暂时没找着链接
step2 添加spring配置文件,不再需要MyBatis的配置文件
<?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:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org /schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <!-- 配置连接池 --> <!-- 读取属性文件 --> <util:properties id="db" location="classpath:config.properties"> </util:properties> <!-- 配置连接池,可以参考DBUtil的方法,这里采用spring创建连接池--> <!-- destroy-method方法作用是:当spring容器关闭后,会将连接释放回到连接池,避免资源浪费 --> <bean id="ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="#{db.driver}"/> <property name="url" value="#{db.url}" /> <property name="username" value="#{db.user}" /> <property name="password" value="#{db.pwd}" /> </bean> <!-- 配置SqlSessionFactoryBean --> <bean id="ssfb" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 指定连接资源 --> <property name="dataSource" ref="ds"/> <!-- 指定映射文件:entity包下的所有后缀xml的映射文件 --> <property name="mapperLocations" value="classpath:entity/*.xml"/> </bean> <!-- 配置MapperScannerConfigurer --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 注入映射器所在的包名 --> <property name="basePackage" value="dao"/> <!-- 只扫描有特定注解的接口 --> <property name="annotationClass" value="annotations.MyBatisRepository" /> </bean> </beans>
可以在spring配置文件中,添加SqlSessionFactoryBean来代替单独使用MyBatis时,需要加载sqlMapConfig.xml。MyBatis创建sqlSessionFactory时,会加载这个配置文件,完成初始化连接池,以及读取映射文件后将sql预编译后存入一个Map集合两项工作,配置sqlSessionFactoryBean也完成了上述两项工作,其主要交给Spring来自动完成。
step3 写实体类,属性名和表格的字段名一样
public class Employee { private int id; private String name; private int age; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", age=" + age + "]"; } }
step4 写了具体sql的xml映射文件,跟MyBatis写法一样,要注意的是namespace是mapper映射器的包名+类名
<?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="dao.EmployeeDAO"> <!-- id要求唯一 parameterType:填写实体类的完整名字 --> <!-- 插入语句 --> <insert id="save" parameterType="entity.Employee"> INSERT INTO T_TABLE VALUES(6,#{name},#{age}) </insert> <!-- 根据id查询语句 --> <select id="findByID" parameterType="int" resultType="entity.Employee"> SELECT * FROM T_TABLE WHERE ID=#{id} </select> <!-- 查询所有结果,不需要参数类型 --> <select id="findAll" resultType="entity.Employee"> SELECT * FROM T_TABLE </select> <!-- 修改操作 --> <update id="modify" parameterType="entity.Employee"> UPDATE T_TABLE SET NAME=#{name},AGE=#{age} WHERE ID=#{id} </update> <!-- 删除操作 --> <delete id="delete" parameterType="int"> DELETE FROM T_TABLE WHERE ID=#{ididid} </delete> <!-- 返回map类型的结果 --> <!-- 也可以将返回结果简写成map,map即为java.util.Map --> <select id="findOne" parameterType="int" resultType="java.util.Map"> SELECT * FROM T_TABLE WHERE ID=#{id} </select> <!-- 使用resultMap解决表的字段名和实体类的属性名不一致的情况 --> <resultMap id="resultMapID" type="entity.NewEmployee"> <result property="empID" column="id" /> <result property="empName" column="name" /> <result property="empAge" column="age" /> </resultMap> <select id="findOneByNewEmp" parameterType="int" resultMap="resultMapID"> SELECT * FROM T_TABLE WHERE ID=#{id} </select> </mapper>
step5 Mapper映射器:一个接口,里面写好了方法,跟MyBatis配置时一样,主要目的为调用方法时能依据命名空间和其他约束条件找到对应的sql
import java.util.List; import java.util.Map; import org.springframework.stereotype.Repository; import annotations.MyBatisRepository; import entity.Employee; import entity.NewEmployee; /** * Mapper映射器 * @author clyang */ @Repository("empDAO") @MyBatisRepository public interface EmployeeDAO { //将一条数据插入数据库 public void save(Employee e); //查询所有结果 public List<Employee> findAll(); //根据id来查找结果 public Employee findByID(int id); //修改操作 public void modify(Employee e); //删除操作 public void delete(int id); //返回类型为map的查询,根据id来查询 public Map findOne(int id); //当表的字段名和实体类的属性名不一致时,根据id来查询 public NewEmployee findOneByNewEmp(int id); }
step6 配置MapperScannerConfigurer
配置参考上上图
该bean会扫描指定包及其子包下面的所有mapper映射器(即接口),并调用session.getMapper()方法获得映射器的具体实现,比如MyBatis例子中的EmployeeDAO dao=session.getMapper(EmployeeDAO.class),并且将这些实现后的对象添加到spring容器中,对应的bean id为接口首字母小写,可以使用repository("别名")来,重命名bean id,方便业务层调用。
测试代码:
import java.util.List; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import dao.EmployeeDAO; import entity.Employee; public class testCase { @Test public void test1() { //启动spring容器 String config="spring-mybatis.xml"; ApplicationContext ac=new ClassPathXmlApplicationContext(config); //调用mapper映射器实现类对象 EmployeeDAO dao=ac.getBean("empDAO",EmployeeDAO.class); //调用查询方法 List<Employee> list=dao.findAll(); System.out.println(list); //不需要手动关闭连接 } //下面略去 }
测试时只要启动Spring容器,Spring会根据配置自动完成MyBatis中需要手动完成的工作,如得到一个sqlSession,创建一个Mapper映射器具体实现对象。
Spring容器实现Mapper映射器具体实现,采用了接口指向对象,这为Java多态的使用,根据接口具体实现方法的不同,实现方法动态调度
测试结果:
(2)只扫描特定的接口
为什么只扫描特定的接口,因为dao下的Mapper映射器接口,有些可能不是采用MyBatis来实现连接,可能采用其它的连接方式,如果是JDBC实现的dao类,也会被MapperScannerConfigure扫描到,但是扫描到后无法使用,会导致程序报错,为了解决这个问题,需要做到只扫描特定的接口
方法:
step1 开发一个注解,注解只是一个标识,代表只扫描它,其他的的不扫描
/** * 一个标识 * @author clyang */ public @interface MyBatisRepository { }
step2 将该注解添加到需要扫描的接口之上
step3 修改MapperScannerConfigurer,告诉它只扫描有注解的接口
总结:Spring集成MyBatis后,充分发挥了Spring的管理对象之间关系的能力,配置好后,自动完成以前MyBatis需要手动完成的步骤