😉😉 学习交流群:
✅✅1:这是孙哥suns给大家的福利!
✨✨2:我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料
🥭🥭3:QQ群:583783824 📚📚 工作微信:BigTreeJava 拉你进微信群,免费领取!
🍎🍎4:本文章内容出自上述:Spring应用课程!💞💞
💞💞5:以上内容,进群免费领取呦~ 💞💞💞💞
一: Spring整合持久层
1:Spring技术为什么要与持久层技术进行整合?
JavaEE开发过程中我们需要持久化框架才能进行数据库的访问操作。JDBC、Hibernate、 MyBatis进行持久层过程中存在大量的代码冗余。Spring基于模板设计模式对这些持久层技术作出了封装。
Spring基于模板设计模式对持久层框架封装之后呢,开发效率提升很多
2:Spring能与哪些持久层技术进行整合?
目前所有的主流层持久层技术都能进行整合
JDBC:基于JDBCSpring提出了一个JDBCTemplate这样的一个类对JDBC进行了封装,这是它与JDBC的整合
Hibernate(JPA):基于HibernateSpring提出了HibernateTemplate这样的一个工具类对Hibernate进行了封装。
MaBatis:基于Mybatis,Spring提供了SqlSessionFactoryBean MapperScannerConfigure这样的工具类简化Mybatis开发
二:Spring整合MyBatis
Spring整合Mybatis的本质在于Spring对于Mybatis的使用有不满意的地方,所以对Mybatis作出合理的封装,使持久层开发变得更加的简洁
1:Mybatis的开发过程:
1、实体
2、实体别名
3、建立表
4、创建Dao接口
5、实现Mapper文件
6、注册Mapper文件
7、MybatisApi的调用
2:Mybatis开发存在的问题
配置繁琐,代码冗余
1、配置了使用别名,这样的配置文件就很繁琐,这样的配置大量出现。
2、所有的Mapper文件都需要注册到核心配置文件上。
3、Mybatis开发过程总Api调用过程中创建SqlSession对象的也很冗余
4、获取Mapper对象的时候也非常的冗余
3:Spring整合Mybatis整合思路分析
Spring整合Mybatis的目的在于简化Mybatis开发,主要是从两个方面着手:
Spring对于创建SqlSessionFactory对象的创建过程做了一个封装,Spring提供了一个SqlSessionFactoryBean专门用于创建SqlSessionFactory对象,我们在Spring当中只需要在配置文件中进行响应的配置,将这个SqlSessionFactoryBean配置到Spring的核心配置文件当中,交由Spring工厂创建他的对象,经过这样的配置,这个对象就被创建出来,在创建这个类的时候,Mybatis读取了一个Mybatis-config.xml的配置文件。
作为这个配置文件来讲,这个配置文件起的作用可以划分为三个环节,第一个是连接池的配置,第二个是类别名的配置,第三个是Sql文件的注册,Mybatis现在需要的这三块内容,在Spring当中通过注入的方式来提供给Mybatis,怎么来完成呢?这里个我们使用的依赖注入的方式,在bean标签当中通过Property标签,name属性是dataSource的属性、typeAliasesPackage、mapperLocations这三个属性,这样原有Mabatis核心配置文件中的三块 内容就通过注入的形式来注入到SqlSessionFactoryBean当中,然后可以为工厂对象创建提供材料,所以,Mybatis核心配置文件也就没有用了。那么这三个注入的三个属性是具体怎么实现的呢?连接池也是一个对象,dataSource是连接池对象,这里应该注入的是Spring整合的连接池对象的ref,引用这个而连接池对象之前需要把连接池对象创建出来,通过bean标签把连接池对象创建出来,连接池是一个用户自建的对象,我们使用Bean前创建好之后,把他进行注入即可。指定实体所对应的包就可以了,里边的实体类就Spring会我们自动创建别名,这个别名就是类名,这个属性在英勇过程中更加的强大,只需要指定包就可以了,对于这个Mapper注册,Spring整合Mybatis的时候MapperLocation当中采用了通配的设置,基于通配的方式例如:*Mapper.xml就可以全部注册进去。
Spring对于创建代理对象的封装比较简单,提供了一个类MapperScannerConfigure这个类,他需要两个要素,一个是SqlSessionFactory对象,一个是Dao层的Class对象,在Bean当中,把SqlSessionFactoryBean注入进去就可以拿到工厂对象,另一个就是Dao接口的class对象,我们指定basePackage的属性,执行这个包名,就可以生成对于Dao的实现类的对象,最终通过这个MapperScannerConfigure这个类就可以创建Dao的实现类的对象,我们这个工具类当中创建的Dao实现类的对象,他们的id值是接口首单词首字母小写
三:Spring与Mybatis整合的开发步骤
1:配置原理
配置文件applicationContext.xml文件的配置
第一步:配置创建SqlSessionFactroy
在这一步当中,我们为了获取这个对象,就需要配置Spring为我们准备的SqlSessionFactoryBean这个类,配置好这个类之后呢就可以获取到SqlSessionFactory这个对象了,我们在Spring核心配置文件当中配置这个类的对象的时候,需要首先创建dataSource数据源的Bean的标签,创建他的对象,然后将这个对象使用Property标签引入到,SqlSessionFactoryBean的对象的创建中,然后需要配置类别名,这个也是对应一个Property标签中的一个typeAliasesPackage属性,在这个属性当中指定实体类所在的包,通过这个配置,以后我们的实体Bean只要是放到这个包中,那么在以后的Mybatis映射中,他的别名就叫做他的类名。然后第三个需要注入的属性是配置文件或者映射文件的路径通用配置等,将来我们的Mapper文件将会放到一个特定的目录里,我们一方面制定了这个目录对应的路径信息,另一方面,我们使用一种通配的方式来适配所有的Mapper文件(com.dashu.mapper/*Mapper.xml),这样就可以将所有的Mapper文件被Spring感知到,并将他们配置到SqlSessionFactory对象当中。这几块的配置极大地简化了开发。
第二步:配置创建DAO接口的实现类
为了实现这个第二部,Spring当中准备了一个MapperScannerConfigure这样的类,作为这个类,他主要的作用是通过session.getMapper()方法获取xxxDao实现类的对象,他这个实现类的XXXDao 实现类的id值是xXXDao,在这个对象当中他需要获取Session对象,通过Session对象获取这个类的dao实现类的对象。所以,在MapperScannerConfigure的Bean标签当中应该将SqlSessionFactoryBean的对象的id值赋值给MapperScannerConfigure的sqlSessionFactoryBeanName属性,按照这个配置就可以找到SqlSessionFactoryBean这个对象,另外一个属性basePacakge指定的是放置Dao的具体的包,Spring通过扫描这个包创建包下所有的Dao的实现类。
总结:
以上的这两种配置的好处在于,只需要配置一次,以后所有的都不需要进行重新配置。
2:开发过程
1:实体Bean
2:表
3:创建Dao接口
4:实现Mapper文件
(一):搭建开发环境
所谓的搭建开发环境指的就是引入Jar包
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dashu</groupId>
<artifactId>spring-mybatis</artifactId>
<version>V1.0.1</version>
<dependencies>
<!--引入druid数据源,这是一个连接池。-->
<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>
<!--Spring对Jdbc封装-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.14.RELEASE</version>
</dependency>
<!--这个是Spring和mybatis整合的JAR包-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
</dependencies>
</project>
(二):Spring配置文件的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--连接池-->
<!--我们使用连接池的本质就是为了创建和数据库的链接。-->
<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/tree?useSSL=false"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<!--创建SqlSessionFactroyBean对象-->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="typeAliasesPackage" value="com.dashu.entity"/>
<property name="mapperLocations">
<list>
<!--这是Spring里边内置的关键字代表Classes目录,也就是java目录-->
<!--/旁边是路径名,/右边是命名规范。-->
<value>classpath:com.dashu.mapper/*Mapper.xml</value>
</list>
</property>
</bean>
<!--创建Dao对象-->
<bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"/>
<property name="basePackage" value="com.dashu.dao"/>
</bean>
</beans>
(三):编码
package com.dashu.Dao;
import com.dashu.entity.User;
/**
* @Auther: DaShu
* @Date: 2021/7/26 20:29
* @Description:
*/
public interface UserDao {
public void save(User user);
}
package com.dashu.test;
import com.dashu.Dao.UserDao;
import com.dashu.entity.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Auther: DaShu
* @Date: 2021/7/26 20:47
* @Description:
*/
public class TestMybatisSpring {
@Test
public void test1(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
UserDao userDao =(UserDao) ctx.getBean("userDao");
User user = new User();
user.setAge(16);
user.setName("liming");
userDao.save(user);
}
}
2021-07-26 20:58:12 DEBUG ClassPathXmlApplicationContext:590 - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@66d33a
2021-07-26 20:58:13 DEBUG XmlBeanDefinitionReader:396 - Loaded 3 bean definitions from class path resource [applicationContext.xml]
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'scanner'
2021-07-26 20:58:13 DEBUG LogFactory:135 - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
2021-07-26 20:58:13 DEBUG ClassPathMapperScanner:437 - Identified candidate component class: file [D:\giteesource\jdbc\spring-mybatis\target\classes\com\dashu\dao\UserDao.class]
2021-07-26 20:58:13 DEBUG ClassPathMapperScanner:49 - Creating MapperFactoryBean with name 'userDao' and 'com.dashu.Dao.UserDao' mapperInterface
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'dataSource'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'sqlSessionFactoryBean'
2021-07-26 20:58:13 DEBUG SqlSessionFactoryBean:49 - Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration
2021-07-26 20:58:13 DEBUG SqlSessionFactoryBean:49 - Parsed mapper file: 'file [D:\giteesource\jdbc\spring-mybatis\target\classes\com.dashu.mapper\UserDaoMapper.xml]'
2021-07-26 20:58:13 DEBUG DefaultListableBeanFactory:213 - Creating shared instance of singleton bean 'userDao'
2021-07-26 20:58:13 DEBUG SqlSessionUtils:49 - Creating a new SqlSession
2021-07-26 20:58:13 DEBUG SqlSessionUtils:49 - SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@152aa092] was not registered for synchronization because synchronization is not active
2021-07-26 20:58:13 DEBUG DataSourceUtils:115 - Fetching JDBC Connection from DataSource
2021-07-26 20:58:14 INFO DruidDataSource:1003 - {dataSource-1} inited
2021-07-26 20:58:14 DEBUG SpringManagedTransaction:49 - JDBC Connection [com.mysql.jdbc.JDBC4Connection@25fb8912] will not be managed by Spring
2021-07-26 20:58:14 DEBUG save:159 - ==> Preparing: Insert into tree (name,age) values (?,?)
2021-07-26 20:58:14 DEBUG save:159 - ==> Parameters: liming(String), 16(Integer)
2021-07-26 20:58:14 DEBUG save:159 - <== Updates: 1
2021-07-26 20:58:14 DEBUG SqlSessionUtils:49 - Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@152aa092]
3:Spring整合Mybatis细节
单纯使用Mybatis进行开发的时候,我们一定会手动记性提交事务,在代码sql执行完毕之后,会有一个session.commit()来提交事务,但是现在使用Spring整合Mybatis之后,并没有在代码中体现事务提交, 这个Dao对象由Spring来为我们进行创建的时候,我们并没有手动提交事务,为什么数据可以插入到数据库当中呢?Connection对象是链接对象,连接对象控制着事务,谁控制着连接对象就变相控制着事务,在整个Spring整合Mybatis之后是谁控制着链接对象呢?在刚才的运行日志中,链接对象并不是交由Spring进行管理,那不是Spring就是Mybatis,本质上控制Connection对象,是连接池对象,当我们使用单纯Mybatis进行开发的时候,Mybatis提供的连接池对象创建链接,Spring和Mybatis整合之后,我们使用的是Druid连接池,他负责Connection对象的创建,这样使用和当时Mybatis提供连接池创建链接对象,有着细微的差别,Mybatis使用自身连接池创建对象之后,调用了一个Connection.setAutoCommit(false),这样就把链接对象中的事务控制改为了手动,这样在操作完成之后,必须手工提交,这就是在Mybatis原生开发的时候必须手动提交,而使用Druid连接池的时候,Connection.setAutoCommit(true)这是默认值,意味着保持着自动控制事务,就是完成一条SQL操作就会自动提交事务,所以,我们使用了Druid链接池之后,是自动提交事务,不需要手动提交。日后换成了其他的连接池之后,都一样,他们的都是true,都是自动提交事务,一条SQL语句都会自动的提交。
答案:Spring和Mybatis整合时引入外部连接池,,保持着自动提交事务的机制(Connection.setaAutoCommit(true)不需要手动提交事务)
注意:
未来实战中,我们设计到多条SQL提交,我们需要把多条SQL设置成一个整体,手工控制成一个事务(Sql一起成功,一起失败),将来呢在Spring当中,Spring会通过他的事务控制,解决这个问题**