文章目录
MyBatis与Spring整合
通过与Spring的整合,MyBatis的SessionFactory交由Spring来构建。构建时需要在Spring的配置文件中添加数据库连接的四大属性来配置数据源。
在单独使用mybatis的情况下,我们通常是通过SqlSessionFactory创建SqlSession,然后通过SqlSession来进行增删查改操作,mybatis整合spring之后,只需要在配置文件中配置sqlSessionFactory,然后使用的时候加载配置文件ApplicationContext,然后直接通过它的getBean()获取bean实例就行。
SqlSessionFactory是mybatis的核心,当与spring进行整合时,我们使用mybatis-spring提供的SqlSessionFactoryBean 来创建其实例(SqlSessionFactory),SqlSessionFactoryBean实现了FactoryBean 接口。SqlSessionFactoryBean的配置有2种风格:
MyBatis与Spring整合步骤
-
导入相关jar包(maven导入依赖)
-
在Spring中配置MyBatis工厂
<!-- 在Spring配置文件中 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/springtest?characterEncoding=utf8" />
<property name="username" value="root" />
<property name="password" value="123456" />
</bean>
<!-- 配置MyBatis工厂,同时指定数据源,并与MyBatis完美整合 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- configLocation的属性值为MyBatis的核心配置文件 -->
<property name="configLocation" value="classpath:com/mybatis/mybatis-config.xml"/>
</bean>
- 使用Spring管理MyBatis的数据操作接口
使用Spring管理MyBatis的数据操作接口的方式有多种。其中,最常用最简洁的一种是基于MapperScannerConfigurer的整合。该方式需要在Spring的配置文件中加入以下内容:
<!--Mapper代理开发,使用Spring自动扫描MyBatis的接口并装配
(Spring将指定包中所有被@Mapper注解标注的接口自动装配为MyBatis的映射接口) -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- mybatis-spring组件的扫描器。com.dao只需要接口(接口方法与SQL映射文件中相同)-->
<property name="basePackage" value="com.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
案例实现(spring-mybatis整合对Student学生进行增删查改)
1. 创建javabean 学生类Student
//创建学生类
public class Student {
private Integer stuId; //学生id
private String stuName; //学生名
private String stuClass; //学生班级
private float stuScore; //学生成绩
//省略getter/setter、toString方法
}
2. 创建接口StudentMapper
@Repository
public interface StudentMapper {
// 只要建立接口,具体实现由spring执行(动态代理)
//通过id获取学生
// com.xgf.mybatis_spring.dao.StudentMapper.getStudentById完全限定名来找sql语句
public Student getStudentById(String stuId);
//增加学生
public boolean addStudent(Student user);
//通过查询学生
public List<Student> getAllStudent();
//更新学生信息 - 通过student对象的stuId来更新
boolean updateStudent(Student student);
//通过id删除学生
boolean deleteStudent(String stuId);
//将student的属性名和值封装成map对象 Map<stuid,123>
List<Map<String, Object>> listStudentMap();
}
3. 创建jdbc连接的属性文件db.properties
jdbc.driver = com.mysql.jdbc.Driver
jdbc.url = jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8
jdbc.username = root
jdbc.password = 123456
4. 配置Spring核心配置文件,由Spring管理MyBatis
applicationContext.xml
<?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:mybatis="http://mybatis.org/schema/mybatis-spring" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<!--1. 引入jdbc的属性文件,在配置中通过占位使用 -->
<context:property-placeholder location="classpath*:db.properties" />
<!--2. <context:component-scan>扫描包中注解所标注的类(@Component、@Service、@Controller、@Repository) -->
<context:component-scan base-package="com.xgf.mybatis_spring"/>
<!--3. 由spring管理 配置数据源数据库连接(从jdbc属性文件中读取参数) -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="url" value="${jdbc.url}"/>
<property name="driverClassName" value="${jdbc.driver}"/>
</bean>
<!--
配置mybatis
创建sqlsessionFactory 管理连接池
sqlSessionFactory sqlSesion工厂 每个sqlSession 对应一个 Connection
所有的数据库的增删查改通过sqlSession来完成
通过connection.preparedStatment() ; 获取结果集ResultSet
-->
<!--4. 通过完全限定名匹配查找 创建SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- 如果完全限定名com.xgf.mybatis_spring.dao与实际名不相同,通过以下配置可以解决找不到问题 -->
<!-- 如果dao包下面还有目录 value="com/xgf/mybatis_spring/dao/**/*.xml" -->
<!--
<!–配置要加载的xml,可以指定在某个路径下–>
<property name="mapperLocations" value="com/xgf/mybatis_spring/dao/*.xml"/>
<!– 配置mybtais中的所有属性 –>
<property name="configuration">
<bean class="org.apache.ibatis.session.Configuration">
<property name="mapUnderscoreToCamelCase" value="true"/>
</bean>
</property>-->
</bean>
<!-- 5. mybatis提供的一个注解扫描标签(搜索映射器 Mapper 接口),通过自动扫描注解的机制,创建每个dao接口定义的bean -->
<mybatis:scan base-package="com.xgf.mybatis_spring.dao"/>
<!-- 6. 配置事务管理器 完成手动事务管理 由spring管理事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--
支持注解驱动的事务管理,指定事务管理器。
配置事务 提供回滚,发生异常数据回滚 需要在类/方法上写注解 @Transactional -->
<tx:annotation-driven transaction-manager="transactionManager"/>
</beans>
5. 编写测试类,测试增删查改功能
//测试类 测试spring-mybatis整合 进行增删查改
public class TestStudent {
private static ApplicationContext applicationContext = null;
private static StudentMapper studentMapper = null;
//静态代码块 只加载一次
static {
//加载配置文件
applicationContext = new ClassPathXmlApplicationContext("com/xgf/mybatis_spring/config/applicationContext.xml");
//通过类获取bean的两种方式
// 1.类名首字母小写
// studentMapper = (StudentMapper) applicationContext.getBean("studentMapper");
// 2.类.class
studentMapper = (StudentMapper) applicationContext.getBean(StudentMapper.class);
}
//测试getStudentById()方法 通过id查询
@Test
public void test01(){
System.out.println("===查找id为2017401300的student:===");
Student std1 = studentMapper.getStudentById("2017401300");
System.out.println(std1);
}
//测试添加
@Test
public void test02(){
/*设置了user的id为自动增长所以不需要设置id*/
Student addStd = new Student(null,"save student","测试student添加",98);
boolean flag = studentMapper.addStudent(addStd);
System.out.println("是否添加成功:" + flag);
}
//测试查询所有student信息,通过三种遍历list方式输出
@Test
public void test03(){
//3种遍历list输出方法
// 3.1、for循环遍历
System.out.println(" ===查找所有student对象===");
List<Student> studentList = studentMapper.getAllStudent();
for (Student student : studentList) {
System.out.println(student);
}
// 3.2、通过流stream方式遍历
System.out.println("\n ===通过流stream方式遍历-->输出student对象集合=== ");
//@FunctionalInterface 函数式接口
studentList.stream().forEach(new Consumer<Student>(){
//接收对象 对Student对象的处理
@Override
public void accept(Student student) {
System.out.println(student);
}
});
// 3.3、通过函数式接口方式遍历 函数式接口只有一个方法被调用
// (函数式接口方法声明)->{方法代码}
System.out.println("\n ===函数式接口方法遍历输出 === ");
studentList.stream().forEach(student->{
System.out.println(student);
});
}
//更新student--通过student对象的stuId来更新
@Test
public void test04(){
System.out.println(" === 假设更新id为2020211236 ===");
Student updateStudent = studentMapper.getStudentById("2020211236");
System.out.println("更新前: " + updateStudent);
boolean flag = studentMapper.updateStudent(new Student(2020211236,"更新studentName","2020软件1班",96));
if(flag == true){
System.out.println("更新后:" + studentMapper.getStudentById("2020211236"));
}else {
System.out.println("更新失败,学生id不存在");
}
}
//测试删除
@Test
public void test05(){
boolean flag = studentMapper.deleteStudent("2020211240");
if(flag){
System.out.println("删除成功");
}else{
System.out.println("删除失败,指定id的学生不存在");
}
}
//测试将student的属性名和值封装成map键值对的形式输出
@Test
public void test06(){
// 返回Map 每一个Map中,key=user对象的属性名,value=user对象的属性值,一个Map封装了一个user对象
List<Map<String,Object>> listStudentMap = studentMapper.listStudentMap();
System.out.println(listStudentMap);
// 1、普通for循环方式输出map
for(Map<String,Object> map: listStudentMap){
// 循环map输出Entry
for(Map.Entry<String,Object> entry: map.entrySet()){
String key = entry.getKey();
Object value = entry.getValue();
System.out.println("key : "+key+"\t value : "+value);
}
}
// 2、函数式接口 输出map
listStudentMap.stream().forEach((Map<String, Object> userMap)->{
// 循环输出map的key和value
userMap.forEach((String key, Object value)->{
System.out.println(key+" : "+value);
});
});
}
}