04 Spring 集成 MyBatis
将 MyBatis 与 Spring 进行整合,主要解决的问题就是将 SqlSessionFactory 对象交由 Spring 来管理。所以,该整合只需要将 SqlSessionFactory 的对象生成器 SqlSessionFactoryBean 注册在 Spring 容器中,再将其注入给 Dao 的实现类即可完成整合。
实现 Spring 与 MyBatis 的整合。常用的方式:扫描的 Mapper 动态代理。Spring 像插线板一样,mybatis 框架是插头,可以容易的组合到一起。插线板 spring 插上 mybatis,两个框架就是一个整体。
4.1 Spring 的事务管理
事务原本是数据库中的概念,在实际项目的开发中,进行事务的处理一般是在业务逻辑层, 即 Service 层。这样做是为了能够使用事务的特性来管理关联操作的业务。
在 Spring 中通常可以通过以下两种方式来实现对事务的管理:
(1)使用 Spring 的事务注解管理事务
(2)使用 AspectJ 的 AOP 配置管理事务(声明式事务管理)
4.2 Spring 中事务的五大隔离级别
读未提交(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
读已提交(Read Committed):只能读取到已经提交的数据。Oracle 等多数数据库默认都是该级别 (不重复读)
可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB 默认级别。在 SQL 标准中,该隔离级别消除了不可重复读,但是还存在幻象读,但是 innoDB 解决了幻读
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
4.3 不同数据库的隔离级别(面试点)
MySQL:mysql 默认的事务处理级别是'REPEATABLE-READ',也就是可重复读
Oracle:oracle 数据库支持 READ COMMITTED 和 SERIALIZABLE 这两种事务隔离级别。
默认系统事务隔离级别是 READ COMMITTED,也就是读已提交
4.4 Spring 事务的传播特性
总结:
常用
PROPAGATION_REQUIRED:必被包含事务
PROPAGATION_REQUIRES_NEW:自己新开事务,不管之前是否有事务
PROPAGATION_SUPPORTS:支持事务,如果加入的方法有事务,则支持事务,如果没有,不单开事务
PROPAGATION_NEVER:不能运行中事务中,如果包在事务中,抛异常
PROPAGATION_NOT_SUPPORTED:不支持事务,运行在非事务的环境
不常用
4.5 @Transactional 的参数讲解
示例:
@Transactional(readOnly = false, // 读写事务
timeout = -1, // 事务的超时时间不限制(数据库有异常或没有连接上,等待的时间,但还是要看连接的数据库是如何设置的。
//noRollbackFor = ArithmeticException.class, // noRollbackFor设置遇到指定的错误不用回滚。此处是遇到数学异常不回滚
isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认
propagation = Propagation.REQUIRED // 事务的传播行为,此处是指当前的方法要在事务中去执行。
)
复制代码
@Transactional 有几点需要注意
只能声明在 public 的 method。原因是 spring 是通过 JDK 代理或者 CGLIB 代理的,生成的代理类,只能处理 public 方法,注解放在类名称上面,这样你配置的这个 @Transactional 对这个类中的所有 public 方法都起作用,@Transactional 在方法名上,只对这个方法有作用,同样必须是 public 的方法。
不能被类内部方法调用。还是因为代理的原因,类内部自调用,不会经过代理类,所以 @Transactional 不会生效
4.6 MyBatis 框架与 Hibernate 框架使用的事务管理器(面试点)
4.6.1 Spring+MyBatis 的事务管理器配置
<!-- 定义事务管理器 -->
<bean id="transactionManager" class="**org.springframework.jdbc.datasource.DataSourceTransactionManager**">
<property name="dataSource" ref="dataSource" />
</bean><!--使用注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />
复制代码
4.6.2 Spring+ Hibernate 的事务管理器配置
<!-- 事务管理器配置,单数据源事务 -->
<bean id="transactionManager" class="**org.springframework.orm.hibernate3.HibernateTransactionManager**">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
复制代码
4.7Spring 中事务的实现
Spring 中事务的实现有两种方式,一种是基于 xml 文件的实现,一种是基于注解方式实现。在 SSM 的开发中,多使用注解方式实现事务的处理。
4.7.1 基于 xml 方式的实现
实现步骤:
(1) 导入相关依赖
<dependencies>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--aspectj依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--spring核心ioc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--做spring事务用到的-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!--mybatis和spring集成的依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
<!--阿里公司的数据库连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency> </dependencies><build>
<!--目的是把src/main/java目录中的xml文件包含到输出结果中。输出到classes目录中-->
<resources>
<resource>
<directory>src/main/java</directory><!--所在的目录-->
<includes>
<!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<!--所在的目录-->
<includes>
<!--包括目录下的.properties,.xml 文件都会扫描到-->
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
复制代码
(2) 引入 aop 名称空间
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A73eKdcL-1658763749525)(../../../../Pictures/Spring/wps292.jpg)](https://img-blog.csdnimg.cn/cb116a19eb484cf99a3e2eceafbce2e8.jpeg)
(3) 引入 tx 名称空间
(4) 配置事务
<!--声明式事务的配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--使用xml方式声明事务-->
<!--配置切面的属性,哪些方法需要添加什么事务传播特性-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*get*" read-only="true"/>
<tx:method name="*select*" read-only="true"/>
<tx:method name="*find*" read-only="true"/>
<tx:method name="*search*" read-only="true"/>
<tx:method name="*add*" propagation="REQUIRED" />
<tx:method name="*save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
<tx:method name="*insert*" propagation="REQUIRED" no-rollback-for="ArithmeticException"/>
<tx:method name="*delete*" propagation="REQUIRED"/>
<tx:method name="*remove*" propagation="REQUIRED"/>
<tx:method name="*clean*" propagation="REQUIRED"/>
<tx:method name="*update*" propagation="REQUIRED"/>
<tx:method name="*modify*" propagation="REQUIRED"/>
<tx:method name="*set*" propagation="REQUIRED"/>
<tx:method name="*change*" propagation="REQUIRED"/>
<tx:method name="*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--使用AOP的技术进行切入点织入-->
<aop:config >
<!--切入点表达式:指定在哪个包下的哪些类中的哪些方法添加事务处理-->
<aop:pointcut id="pointcat" expression="execution(* com.bjpowernode.service.*.*(..))"></aop:pointcut>
<!--完成切面与切入点绑定-->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcat"></aop:advisor>
</aop:config>
复制代码
4.7.2 基于注解方式实现
(1)导入相关依赖(同 xml 方式)
(2)配置注解驱动
<!--声明式事务的配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean> <!-- 配置注解驱动-->
<tx:annotation-driven></tx:annotation-driven>
复制代码
(3)@Transactional 设置传播特性
@Service
//交给Spring接管,进行对象的创建,并且自动注入mapper
@Transactional( propagation = Propagation.*REQUIRED*
//必须添加事务
,readOnly = true
//只读事务(用于查询操作)
,timeout = -1 //设置连接永不超时
,noRollbackForClassName = "ArithmeticException"
//遇到这个异常不回滚事务
,isolation = Isolation.*DEFAULT*
//使用数据库的隔离级别
) public class UsersServiceImpl implements UsersService {
复制代码
4.7.3 Spring+MyBatis 整合案例
整合实现步骤:
1.新建 maven 工程,添加各种依赖
2.修改目录结构
3.添加 SqlMapConfig.xml 和 XXXMapper.xml 模板
4.添加 db.properties 文件
5.添加 SqlMapConfig.xml 文件
6.添加 applicationContext_dao.xml 文件并实现功能
7.添加 applicationContext_service.xml 文件并实现功能(注解驱动)
8.添加 applicationContext_trans.xml 文件(xml 配置文件方式)
<!-- 导入applicationContext_dao.xml文件-->
<import resource="classpath:applicationContext_dao.xml"></import>
<!-- 为Spring框架管理的业务逻辑层的对象配置扫描器,因为我们是使用注解的方式进行开发-->
<context:component-scan base-package="com.bjpowernode.service"></context:component-scan>
<!-- 进行事务管理器的配置,分别由各自框架自己的事务管理器进行事务的管理 DataSourceTransactionManager:MyBatis框架的事务管理器
一定要进行数据源的配置,因为事务一定是访问数据库的 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 使用xml配置的方式进行事务管理-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 查询操作都设置为只读事务-->
<tx:method name="get*" read-only="true" />
<tx:method name="select*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<!-- 增删改的操作必要添加事务REQUIRED-->
<tx:method name="insert*" propagation="REQUIRED"></tx:method>
<tx:method name="add*" propagation="REQUIRED"></tx:method>
<tx:method name="save*" propagation="REQUIRED" no-rollback-for="ArithmeticException"></tx:method>
<tx:method name="set*" propagation="REQUIRED"></tx:method>
<tx:method name="update*" propagation="REQUIRED"></tx:method>
<tx:method name="modify*" propagation="REQUIRED"></tx:method>
<tx:method name="change*" propagation="REQUIRED"></tx:method>
<tx:method name="delete*" propagation="REQUIRED"></tx:method>
<tx:method name="remove*" propagation="REQUIRED"></tx:method>
<tx:method name="clear*" propagation="REQUIRED"></tx:method>
<tx:method name="empty*" propagation="REQUIRED"></tx:method>
<!-- 其它方法支持事务就行-->
<tx:method name="*" propagation="SUPPORTS"></tx:method>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- 指定切入点表达式,切入到业务逻辑层上-->
<aop:pointcut id="pointcut" expression="execution(* com.bjpowernode.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor> </aop:config>
复制代码
9.新建库 springuser,新建表 users,accounts
10.新建实体类 Users,Accounts
11.新建 mapper 包下的接口和.xml 文件
12.新建 service 包下的接口和接口实现类
13.新建测试类,完成功能测试
测试结果总结如下:
4.8 Spring Bean 的生命周期
4.8.1 Spring Bean 的生命周期图示
Spring 作为当前 Java 最流行、最强大的轻量级框架,受到了程序员的热烈欢迎。
准确的了解 Spring Bean 的生命周期是非常必要的。
我们通常使用 ApplicationContext 作为 Spring 容器,这里我们讲的也是 ApplicationContext 中 Bean 的生命周期。
4.8.2 Spring Bean 的生命周期中各种方法分类
Bean 的完整生命周期经历了各种方法调用,这些方法可以划分为以下几类:
1、Bean 自身的方法:这个包括了 Bean 本身调用的方法和通过配置文件中<bean>的 init-method 和 destroy-method 指定的方法
2、Bean 级生命周期接口方法:这个包括了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这些接口的方法
3、容器级生命周期接口方法:这个包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
4、工厂后处理器接口方法:这个包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
总结:class(UsersService)-实例化-对象属性填充(AccountsService)-初始化(DefaultUsers)AOP-代理对象-bean.
@Service
//交给Spring去创建对象
IOC@Transactional =èAOP处理
public class UsersServiceImpl implements UsersService {
//切记切记:一定有数据访问层的对象
@Autowired
UsersMapper usersMapper;
//由Spring负责依赖注入
IOCDefaultUsers users;=è初始化处理的对象
@Override
public int insert(Users users) {
int num = usersMapper.insert(users)***\*;
System.out.println("用户增加成功!num="+num);
System.out.println(1);
return num;
}
}
复制代码
4.9 Spring 中用到的设计模式总结
Spring 框架中用到了很多的设计模式,总结如下:
工厂模式:Spring 通过工厂模式 BeanFactory,ApplicationContext 创建 Bean 对象。
代理设计模式:SpringAOP 的实现,底层使用了动态代理模式。
单例模式:Spring 中的 Bean 默认都是单例的。
模板方法模式:Spring 中 jdbcTemplate,hibernateTemplate 等以 Template 结尾的类都用到了模板模式。
装饰模式:我们的项目需要连接多个数据库,而不同的客户在访问时可能会访问不同的数据库,这种模式可以让我们根据用户的需求动态的切换数据库。
观察者模式:Spring 的事件驱动是观察者模式的应用。
适配器模式:SpringAOP 的增强功能使用到了适配器模式。
评论