在之前我们学习了Spring的控制反转以及AOP思想,那么我们如何将这些应用到我们的项目中呢?我们知道,通过MyBatis框架可以实现对数据库的操作,而通过Spring框架的IoC、AOP等机制,能够对项目中的组件进行解耦管理,建立一个低耦合的应用架构。将Spring框架与MyBatis框架整合在一起,在对组件实现解耦的同时,还能使MyBatis的使用变得更加方便、简单。此外,通过Spring的声明式事务等,还可以进一步简化编码,减少开发工作量,提高效率,当然这是后话,今天我们只实现两个框架的简单整合。
作为Bean容器,Spring框架提供了IoC机制,可以接管所有组件的创建工作并进行依赖管理,因此整合的主要工作就是把MyBatis框架使用过程中所涉及的核心组件配置到Spring容器中,交给Spring来管理。
具体来说,业务逻辑对象依赖基于MyBatis技术实现的DAO层对象,核心即是获取SqlSession实例。再往上翻,获取SqlSession则需要依赖SqlSessionFactory实例。再往上翻一层,SqlSessionFactory是依赖SqlSessionFactoryBuilder读取MyBatis的配置文件中的数据源、SQL映射文件等信息来构建。
针对上述关系,我们只需要将以上这些流程全部交给Spring,由Spring来接管这一工作,实现解耦。
准备所需要的jar包(这里只列出整合需要依赖的新jar包,以往的jar包请自行准备。x代表任意版本号)
mybatis-spring-x.x.x.jar
spring-jdbc-x.x.x.RELEASE.jar
spring-tx-x.x.x.RELEASE.jar
commons-dbcp-x.x.jar
commons-pool-x.x.jar
分享一下Spring所有的依赖包、整合所需要的所有依赖包以及Spring源码下载地址
https://pan.baidu.com/s/1HYqfU85-jPkHmDJeUFoWHA
1、新建Web项目(本文使用的开发工具是IDEA),目录结构如下,实体类、接口、映射文件等请自行创建。
2、新建数据库Blog,新建数据库表Student
DROP TABLE IF EXISTS `Student`;
CREATE TABLE `Student` (
`ID` int(4) NOT NULL AUTO_INCREMENT,
`StuName` varchar(10) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3、将所需依赖包导入至项目中
1、在实体类中声明属性id、stuName,并生成getter、setter方法。
2、在数据层接口StudentDao、服务层接口StudentService中定义如下方法
public Student getStudent(@Param("id") int id); //根据ID查找学生对象
3、在服务层StudentServiceImpl中实现StudentService接口,并定义SqlSessionTemplate属性,生成其setter方法(至于这个类到底是干嘛的,在下文介绍配置文件时进行讲解)。
private SqlSessionTemplate sqlSession; //为其生成setter方法
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public Student getStudent(@Param("id") int id) {
return sqlSession.getMapper(StudentDao.class).getStudent(id);
}
4、在resource文件夹下新建mybatis-config.xml文件(MyBatis的配置文件),注意一定要把resource文件夹设置为编译文件夹,或者你可以直接将这些配置文件放在src目录下,个人习惯。
相比于之前,MyBatis的配置文件就显得简单很多,我们在这里只指定一个包含实体类的包,设置日志为LOG4J,自动映射级别为FULL,至于数据库环境、SQL映射文件,全部移交到Spring的配置文件中。
5、在resource文件夹下创建spring-mybatis.xml配置文件
classpath:com/Blog/Mapper/*.xml
在以上配置文件中,除去最后装配我们的业务组件(为StudentServiceImpl类中的SqlSessionTemplate对象注入依赖),Spring与MyBatis的整合大概可分为三步:配置数据源、配置SqlSessionFactoryBean、配置SqlSessionTemplate。
配置数据源
对于任何持久化解决方案,连接数据库都是首要的问题。在Spring中,数据源作为一个重要的组件可以单独进行配置和维护。首先我们要选择一种具体的数据源实现技术,目前流行的数据源实现有dbcp、c3p0、Proxool等,它们都实现了连接池功能,这里以dbcp为例。其他数据源技术的配置都与此类似,只需要下载不同的jar包即可,可自行查阅资料进行学习。
因为我们的url属性中有特殊符号“&”,所以使用进行标记。
配置SqlSessionFactoryBean
从这个类的名称就可以看出来,它肯定与SqlSessionFactory有关。在MyBatis中,我们使用SqlSessionFactoryBuilder来创建SqlSessionFactory工厂。而在mybatis-spring集成环境中,可以使用SqlSessionFactoryBean来完成这个工作,它的内部封装了使用SqlSessionFactoryBuilder创建SqlSessionFactory的过程。同样,SqlSessionFactory需要依赖三部分东西:数据源、MyBatis的配置、SQL映射文件,所以就形成了上面的配置文件中的第二步,我们先引用之前定义的数据源组件,再指向MyBatis的配置文件,最后为这个类中的mapperLocations属性注入值,即要引入的SQL映射文件。因为逐个列出映射文件比较繁琐,所以我们使用mapperLocations属性扫描式地加载SQL映射文件,指定一个匹配表达式即可。
配置SqlSessionTemplate
跟之前相似,获得SqlSessionFactory的实例以后就可以获得SqlSession了。只不过在集成环境中为了更好地使用SqlSession,充分利用Spring框架提供的服务,mybatis-spring整合包中提供了SqlSessionTemplate类。这个类实现了SqlSession接口和DisposableBean接口,具有MyBatis中原有的SqlSession的所有操作方法。使用SqlSessionTemplate类可以更好地与Spring服务融合并简化一些工作,可以保证和当前Spring事务相关联、自动管理会话的生命周期、必要的回滚、提交、关闭等,当然这是后话,本文先不介绍。
在Spring容器中定义SqlSessionTemplate组件时,需要通过其构造方法为其注入一个SqlSessionFactory实例,所以我们引用了在第二步配置好的Bean组件。
6、在测试类中进行测试(在MyTest类中添加如下代码)
@Test
public void studentTest(){
ApplicationContext context=new ClassPathXmlApplicationContext("spring-mybatis.xml");
StudentService studentService=(StudentService)context.getBean("studentService");
Student student=studentService.getStudent(1);
System.out.println(student);
}
注:先往数据库插入一条记录,名叫张三,ID为1。
MyBatis与Spring的简单整合到这里就结束了,实现起来还是很简单的,只不过是把之前配置在MyBatis配置文件中的东西拿到Spring配置文件里,再把SqlSessionFactory、SqlSession的实例定义到Spring容器中,通过注入的方式注给需要获取它们的Bean组件,替代之前通过编码的方式获取连接。在下一篇博文中将对整合做一些优化。
====================================最后附上本文中所有的代码========================================
实体类Student
package com.Blog.Entity;
public class Student {
private int id;
private String stuName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getStuName() {
return stuName;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", stuName='" + stuName + '\'' +
'}';
}
}
数据层接口StudentDao
package com.Blog.Dao;
import com.Blog.Entity.Student;
import org.apache.ibatis.annotations.Param;
public interface StudentDao {
public Student getStudent(@Param("id") int id); //根据ID查找学生对象
}
服务层接口StudentService
package com.Blog.Service;
import com.Blog.Entity.Student;
import org.apache.ibatis.annotations.Param;
public interface StudentService {
public Student getStudent(@Param("id") int id); //根据ID查找学生对象
}
服务层接口实现类StudentServiceImpl
package com.Blog.ServiceImpl;
import com.Blog.Dao.StudentDao;
import com.Blog.Entity.Student;
import com.Blog.Service.StudentService;
import org.apache.ibatis.annotations.Param;
import org.mybatis.spring.SqlSessionTemplate;
public class StudentServiceImpl implements StudentService {
private SqlSessionTemplate sqlSession; //为其生成setter方法
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
@Override
public Student getStudent(@Param("id") int id) {
return sqlSession.getMapper(StudentDao.class).getStudent(id);
}
}
SQL映射文件StudentMapper.xml
MyBatis配置文件mybatis-config.xml
Spring配置文件spring-mybatis.xml
classpath:com/Blog/Mapper/*.xml