前几节有点儿肝,虽然有复制粘贴代码但是每篇文章也记录了上万字,接下来内容分成两节记,分别是Spring整合mybatis和事务,这节先记录一下用Spring整合mybatis。
一、持久层的整合
JAVAEE的开发肯定避不开整合持久层,虽然有多种持久层选型比如JDBC、MyBatis、JPA(Hibernate)等,但是统一会遇到的问题就是持久层代码开发过程中存在冗余。所以Spring基于模板设计模式对于上述的持久层技术进行了封装。
模板模式后续有时间可以研究一下:《JAVA设计模式》之模板模式(Template)
Spring整合的持久层技术:
1. JDBC
|- JDBCTemplate
2. Hibernate (JPA)
|- HibernateTemplate
3. MyBatis
|- SqlSessionFactoryBean MapperScannerConfigure
以下就用Mybatis举例子了,其实我平常用JPA和MBG比较多,传统的Mybatis开发早就忘了,简单再回顾一下:
建实体类,建DAO接口,建表,建mapper.xml文件,注册配置mapper.xml文件和配置连接池等等等等,最后用Mybatis的API再去创建会话,再去会话里调用具体业务逻辑并提交事务,烦得要死。
代码测试:
实例类略,建了有无参构造和get set;dao接口略,定义了一个方法。
Mybatis的配置文件,配置了连接池、实体别名、注册了mapper.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>
<typeAliases>
<typeAlias alias="user" type="com.jin.mybatis.User"/>
</typeAliases>
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring_mybatis?useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="1"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserDAOMapper.xml"/>
</mappers>
</configuration>
dao接口的mapper.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.jin.mybatis.UserDAO">
<insert id="save" parameterType="user">
insert into t_users(name,password) values (#{name},#{password})
</insert>
</mapper>
package com.jin.mybatis;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
/**
* @author jinyunlong
* @date 2021/12/8 16:50
* @profession ICBC锅炉房保安
*/
public class TestMyBatis {
public static void main(String[] args) throws IOException {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
UserDAO userDAO = sqlSession.getMapper(UserDAO.class);
User user = new User();
user.setName("opopop");
user.setPassword("fdfdfdfd");
userDAO.save(user);
sqlSession.commit();
}
}
测试方法,将实体对象内容插入表,提交事务。
将如上步骤分为7步:
1. 实体
2. 实体别名
3. 表
4. 创建DAO接⼝
5. 实现Mapper⽂件
6. 注册Mapper⽂件
7. MybatisAPI调⽤
可见除了步骤1、2、4、5必须以外,其他步骤都存在配置繁琐或者代码冗余的问题:
配置繁琐 代码冗余
1. 实体
2. 实体别名 配置繁琐
3. 表
4. 创建DAO接⼝
5. 实现Mapper⽂件
6. 注册Mapper⽂件 配置繁琐
7. MybatisAPI调⽤ 代码冗余
这时候使用Spring工厂可以解决以上两个问题。
二、Spring与MyBatis整合
整合思路如上图,可以通过把Spring包(org.spring.mybatis.xxx)里的类对象交由工厂管理并将上述配置繁琐的几点直接进行注入。创建dao对象的冗余代码也可以交由工厂配置文件解决,引入类对象并注入basePackage,dao对象的名字就是首字母小写,作为bean去被 getbean。
代码测试:
首先需要先引入依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.18</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.48</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
最主要的就是配置文件,主要是看下面三个包(文件夹)的指定路径,分别对应实体包、mapper.xml储存文件夹、dao包。对应实体别名、注册mapper.xml、创建dao对象;因为是对目录的指定,所以只要写一次,目录中文件都会生效:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/spring_mybatis?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="1"></property>
</bean>
<!-- 创建SqlSessionFactory SqlSessionFactoryBean-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="com.jin.entity"></property>
<!-- 指定 实体类所在的包 com.baizhiedu.entity User-->
<!-- Product-->
<property name="mapperLocations">
<list>
<value>classpath:com.jin.mapper/*Mapper.xml</value>
<!-- 指定 配置⽂件(映射⽂件)的路径 还有通⽤配置-->
<!-- com.baizhiedu.mapper/*Mapper.xml-->
</list>
</property>
</bean>
<!-- 创建DAO对象 MapperScannerConfigure-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
<property name="basePackage" value="com.jin.dao"></property>
<!-- 指定 DAO接⼝放置的包 com.baizhiedu.dao-->
</bean>
</beans>
package com.jin;
import com.jin.dao.UserDAO;
import com.jin.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author jinyunlong
* @date 2021/12/9 15:38
* @profession ICBC锅炉房保安
*/
public class TestMybatisSpring {
/*
用于测试:Spring与Mybatis的整合
*/
@Test
public void test1(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
UserDAO userDAO = (UserDAO) ctx.getBean("userDAO");
User user = new User();
user.setName("llll");
user.setPassword("232323");
userDAO.save(user);
}
}
返回结果:
直接工厂调用创建会话并获取对象,解决配置繁琐和代码冗余的问题。配置文件只需要歇一次,之后只要专注于以下4步的编写即可:
1. 实体
2. 表
3. DAO接⼝
4. Mapper⽂件配置
一个细节:Spring和Mybatis整合,事务是自动提交的:
本质上控制连接对象(Connection) ---> 连接池(DataSource)
1. Mybatis提供的连接池对象 ---> 创建Connection
Connection.setAutoCommit(false) ⼿⼯的控制了事务 , 操作完成后,⼿
⼯提交
2. Druid(C3P0 DBCP)作为连接池 ---> 创建Connection
Connection.setAutoCommit(true) true默认值 保持⾃动控制事务,⼀条
sql ⾃动提交
答案:因为Spring与Mybatis整合时,引⼊了外部连接池对象,保持⾃动的事务提交这
个机制(Connection.setAutoCommit(true)),不需要⼿⼯进⾏事务的操作,也能进
⾏事务的提交
注意:未来实战中,还会⼿⼯控制事务(多条sql⼀起成功,⼀起失败),后续Spring通过
事务控制解决这个问题。
三、总结
Spring整合Mybatis:IOC的应用,但不是解耦,是解决配置繁琐和代码冗余的问题。