Spring整合_事务处理

在这里插入图片描述

1.整合日志

1.1概述

spring与日志框架进行整合,日志框架就可以在控制台中输出一些Spring运行过程中的一些重要的信息,便于了解运行过程,利于程序调试

如何整合日志框架

默认
spring1 2 3早期都是commons-logging.jar
spring5.x默认整合的日志框架 logback log4j2

我们也可以整和log4j日志框架

1.2整合log4j

1.导入log4j依赖

<!--   日志框架   -->
   <dependency>
       <groupId>log4j</groupId>
       <artifactId>log4j</artifactId>
       <version>1.2.17</version>
   </dependency>

 <!--  让Spring框架支持log4j 干掉默认的logback和log4j2  -->
   <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-log4j12</artifactId>
       <version>1.7.25</version>
   </dependency>

2.引入log4j.properties配置文件

### 配置根
log4j.rootLogger = debug,console

#显示SQL语句的打印 这里指定dao接口所在的报名
log4j.logger.com.shwsh.simulate.dao=TRACE

### 日志输出到控制台显示
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

2.整合Mybatis

2.1Mybatis编码回顾

大致分为4个步骤

  • 1、表 实体类
  • 2、DAO接口
  • 3、编写DAO接口对应的xxxMapper.xml文件
  • 4、主配置文件中注册xxxMapper.xml文件并编写一些必要配置(数据源 类别名等)
  • 5、API调用 ,获取SqlSessionFactory后获取SqlSession,然后创建DAO接口的代理对象调用方法完成操作

2.2Mybatis开发中存在的问题

在Mybatis开发的过程中,我们要编写Mybatis的主配置文件,mybatis-config.xml,在主配置文件里要编写一些关于别名 数据源 注册Mapper文件的配置,就以注册Mapper文件来说,一般的这些Mapper文件都在一个包中,只是Mapper文件名不一样而已,但是只要有一个Mapper文件我们就需要注册一个,这就很繁琐。

另外就是关于SqlSessionFactory以及SqlSession及DAO接口实现类的创建都会存在大量的代码冗余。

2.3Spring整合Mybatis的基本思路

使用Spring整合Mybatis的基本核心就是使用Spring提供的两个类

SqlSessionFactoryBean 实现了FactoryBean接口

  • 这个类解决的就是关于原始开发中SqlSessionFactory的创建,我们知道,SqlSessionFactory的作用就是将Mybatis的主配置文件封装成一个Configuration对象,然后存到SqlSessionFactory中,后来为了创建SqlSessions对象。
  • ​ 主配置文件核心部分就是数据源 注册mapper等功能,我们可以通过Spring提供的SqlSessionFactoryBean 为其注入这些属性,最终完成SqlSessionFactory的创建。所以我们就不需要写Mybatis的主配置文件了。
  • 我们核心的需要给SqlSessionFactoryBean对象注入一个数据源 一个Mapper文件所在包的信息,还有实体类所在的包名信息(为了起别名)

MapperScannerConfigure

这个类解决的是我们创建SqlSession对象以及最终通过SqlSession对象为我们创建对应的DAO接口的实现类,所以说我们需要注入 上面的SqlSessionFactoryBean 以及 对应的dao接口所在包的信息

在这里插入图片描述

2.4整合Mybatis开发步骤

2.4.1导入Spring整合Mybatis依赖

<!--导入Spring整合Mybatis依赖-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.2</version>
</dependency>
<!--mybatis-spring 依赖需要spring-jdbc的依赖 所以也要引入这个依赖-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>
<!--Druid连接池-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
</dependency>

<!--Mybatis依赖-->
<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>3.4.6</version>
</dependency>

2.4.2编写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" xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://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 name="url" value="jdbc:mysql://ip:3306/xxx?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <!--创建SqlSessionFactory-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--注入数据源信息-->
        <property name="dataSource" ref="dataSource"></property>
        
        <!--注入实体类所在包名信息-->
        <property name="typeAliasesPackage" value="com.shwsh.entity"/>
        
        <!--注入Mapper文件所在位置信息-->
        <property name="mapperLocations" value="classpath:mybatis_conf/mapper/*Mapper.xml">
       
        </property>
    </bean>


    <!--创建SqlSession对象最后创建DAO对象-->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    
    <!--注入SqlSessionFactory对象 为了创建SqlSession-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
	<!--注入dao接口所在的包名信息,为了让SqlSession创建DAO接口的实现类对象-->
 <property name="basePackage" value="com.shwsh.simulate.dao"></property>
    </bean>

</beans>

2.4.3测试

public static void main(String[] args) {
	
    //获取工厂
 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    
    //注意这里我们在配置文件中配置的MapperScannerConfigurer对象就是为了让Spring给我们创建出DAO接口的实现类,我们使用对应的Dao接口的首字母小写就能拿到对应的DAO接口的对象
    UserDao userDao = (UserDao) context.getBean("userDao");
    Boolean result = userDao.insert(new User(null, "ss", "sd"));
    System.out.println(result);
	//true  插入成功
}

2.5整合后关于事务的问题

我们经过2.4节的测试发现,经过Spring整合了Mybatis后,我们的操作可以直接进入数据库,也就是说事务现在是自动提交的,我们知道在Mybatis开发时,我们可以通过SqlSessionFactory在创建SqlSession时指定autocommit为true即设置自动提交,默认autocommit为false即不自动提交。我们知道,控制事务就要控制连接,我们引入了连接池之后连接就是连接池控制的,不管是druid c3p0 还是dbcp等,都是自动提交事务,但是我们在未来的开发中显然不能设置连接自动提交事务,一定要开启事务,所以说我们要事务交给Spring来管理,所以请看下一章 Spring处理事务。

3.Spring事务处理

3.1事务的特性

见MySQL笔记

3.2如何控制事务的本质

JDBC控制事务:
	Connection.setAutoCommit(false) //开启事务
	Connection.commit();            //提交事务
	Connection.rollback();          //回滚
Mybatis控制事务:
	是否开启事务在使用SqlSessionFactory创建SqlSession时即调用openSession时传入true表示自动提交,如果没有传入autocommit默认是开始事务
	sqlSession.commit();   //提交事务
	sqlSession.rollback();   //回滚
 Mybatis底层也封装了Connection,即底层也是通过Connection控制事务
	
结论:控制事务的底层就是控制连接,即Connection对象!!!

3.3Spring处理事务分析

Spring是通过AOP的方式进行事务开发

编码步骤

1、原始对象

这里的原始对象就是我们的Service层 即一个个的xxxServiceImpl

2、额外功能

这里的额外功能就是事务处理 即在目标方法执行前开启事务,执行完后提交事务,如果出现了异常就回滚事务
-------------------------------------------------------------------
原来AOP开发我们需要实现MethodInteceptor接口实现方法,书写原始方法+额外功能,
这里的原始方法+额外功能Spring已经帮我们做好了,封装在DataSourceTransactionManager类里,核心的是我们需要为其注入DataSource对象,即需要控制连接。因为想要控制事务必须要控制连接或是连接池

3、切入点

原来的开发我们需要写切入点表达式,用来标注这些切入点,而在Spring处理事务时
我们只需要使用@Transactional注解标注需要加入事务的地方,可以加在一个类上或者一个方法上
1 如果加在类上,那么这个类的所有方法都会加入事务
2 如果加在方法上,那么这个方法会加入事务

4、组装切面

使用标签进行切入点与额外功能的组装,使用 transaction-manager属性找到额外功能 而切入点在这里不需要配置了,因为我们为需要加入事务的类或者方法加入了@Transactional注解,Spring会自动的扫描这些注解,自动的完成与额外功能的组装
<tx:annotation-driven transaction-manager=""/>

3.4Spring事务编码

3.4.1导入依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.1.14.RELEASE</version>
</dependency>

3.4.2编码

1、原始对象

<bean id="userService" class="com.shwsh.simulate.service.UserServiceImpl">
<!--整合了MapperScannerConfigurer自动帮我们创建了DAO接口的实现类 这里直接引用-->
    <property name="userDao" ref="userDao"></property>
</bean>

2、额外功能

Spring将事务的额外功能封装在DataSourceTransactionManager类里,而且控制事务必须要控制连接或者连接池,所以要将连接对象注入

<!--事务的额外功能-->
<bean id="transacationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!--注入连接 控制事务-->
    <property name="dataSource" ref="dataSource"></property>
</bean>

3、切入点

加上@Transactional注解

@Transactional
@Override
public Boolean register(User user) {
    Boolean insert = userDao.insert(user);
    return insert;
}

4、组装切面

<!--组装事务的额外功能 切入点自动扫描@Transactional注解-->
<tx:annotation-driven transaction-manager="transacationManager"></tx:annotation-driven>

3.5完整配置文件

<?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:aop="http://www.springframework.org/schema/aop"
       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/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx.xsd">

    <!--数据源(连接池)对象-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://8.131.95.64:3306/sunspring?useSSL=false"/>
        <property name="username" value="root"/>
        <property name="password" value="2741404507"/>
    </bean>

    <!--创建SqlSessionFactory 为其注入数据源 包扫描 mapper文件扫描等信息,然后就可以不用书写Myabtis的主配置文件了-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="typeAliasesPackage" value="com.shwsh.simulate.entity"></property>
        <property name="mapperLocations" value="classpath:mybatis_conf/mapper/*Mapper.xml"></property>
    </bean>


    <!--创建SqlSession以及DAO对象-->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
        <property name="basePackage" value="com.shwsh.simulate.dao"></property>
    </bean>
	
    <!--原始对象 为其注入DAO-->
    <bean id="userService" class="com.shwsh.simulate.service.UserServiceImpl">
        <!--整合了MapperScannerConfigurer自动帮我们创建了DAO接口的实现类,这里直接引用即可-->
        <property name="userDao" ref="userDao"></property>
    </bean>

    
    <!--事务的额外功能-->
    <bean id="transacationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--注入连接 控制事务-->
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--组装切面 事务的额外功能 切入点自动扫描@Transactional注解-->
    <tx:annotation-driven transaction-manager="transacationManager"></tx:annotation-driven>

</beans>

3.6关于组装切面代理的切换

  <!--组装切面 也可以使用 proxy-target-class="true"进行动态代理的切换 默认是false即JDK动态代理 为true切换为Cglib动态代理-->
    <tx:annotation-driven transaction-manager="transacationManager" proxy-target-class="true"/>

说明:Spring事务处理底层就是AOP

3.7基于标签的事务配置方式(事务开发第二种方式)

基于注解@Transactional的事务配置回顾


<!--原始类-->
<bean id="userService" class="com.shwsh.simulate.service.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
</bean>

<!--额外功能-->
    <bean id="transacationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!--切入点-->
@Transactional(设置事务属性)
public Boolean register(User user) {
 			
}

<!--整合切面 找到额外功能 并自动扫描@Transactional注解-->
<tx:annatation-driven transaction-manager = "transacationManager"/>

基于标签的配置方式

跟注解的开发步骤不同之处就在于切入点以及事务属性的配置组装切面 这两步

<!--1、原始类-->
<bean id="userService" class="com.shwsh.simulate.service.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
</bean>

<!--2、额外功能-->
    <bean id="transacationManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

<!--3、配置事务属性以及额外功能-->
	<tx:advice id="txAdvice" transacation-manager="dataSourceTransactionManager">
    <tx:attributes>
        	<!--可以使用通配符的方式xxx*-->
          <tx:method name="register" isoloation="",propagation=""></tx:method>
          <tx:method name="login" .....></tx:method>
          等效于 
          @Transactional(isolation=,propagation=,......)
          public void register(){
        
          }
    </tx:attributes>
</tx:advice>

<!--4、组装切面 原始AOP组装法-->
<aop:config>
    <!--切入点--> <!--这里一般都使用包切入点-->
     <aop:pointcut id="pc" expression="execution(* com.baizhiedu.service.UserServiceImpl.register(..))"></aop:pointcut>
    <!--组装切入点+额外功能(第三步配置的)-->
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pc"></aop:advisor>
</aop:config>

4.Spring的事务属性

4.1事务属性分类

  • 隔离属性
  • 传播属性
  • 只读属性
  • 超时属性
  • 异常属性

4.2如何添加事务属性

我们上面在开发Spring事务时,在切入点步骤使用的是Spring为我们提供的@Transcational注解,加了这个注解的类或方法我们的额外功能就会添加上去。

我们添加事务属性就在@Transcational注解中设置值

注解中的每一个属性值都对应上面的事务属性
@Transactional(islocation=,propagation=,readOnly=,timeout=,rollbackFor,noRollbackFor=,)

4.3隔离属性(ISOLATION)及使用

具体参考MySQL初级笔记

4.3.1并发访问导致的问题

  • 脏读 (读到了另外的事务未提交的数据)
  • 不可重复读 (读到了其他事物已提交的数据)
  • 幻读 (对整张表的数据进行了修改)

4.3.2解决问题-设置隔离级别

1.Read Committed   解决脏读             不能解决不可重复读与幻读 

2.Repeatable Read  解决脏读 不可重复读    不能解决幻读  (行锁)    --MySQL默认隔离级别

3.Serializable     解决脏读 不可重复读 幻读            (表锁)

4.3.3隔离级别的并发安全性及效率

并发安全
Read Committed <Repeatable Read<Serializable 

运行效率
Read Committed >Repeatable Read>Serializable 

4.4Spring设置隔离级别

都是在@Transactional注解的isolation属性设置

隔离级别设置为Read Committed
@Transactional(isolation=Isolation.READ_COMMITTED)

隔离级别设置为Repeatable Read  
@Transactional(isolation=Isolation.REPEATABLE_READ)

隔离级别设置为Serializable 
@Transactional(isolation=Isolation.SERIALIABLE)

Spring默认的是Isolation.DEFAULT,即使用的是不同的数据库的默认隔离级别

4.5开发中如何设置隔离级别

开发中使用Spring指定的Isolation.DEFAULT即可,即直接使用不同数据库的默认级别就行

4.4传播属性(Progation)

4.4.1概述

指的就是事务的嵌套 例如Service调用Service 即一个事务包含若干事务

出现的问题:一个事务中包含了很多小的事务,他们彼此影响,最终会导致整个事务丧失原子性

4.4.2传播属性的值及其用法

Spring默认的传播属性是REQUIRED

传播属性的值外部不存在事务外部存在事务用法备注
REQUIRED开启新的事务融合到外部事务中@Transactional(propagation = Propagation.REQUIRED)增删改方法
SUPPORTS不开启事务融合到外部事务中@Transactional(propagation = Propagation.SUPPORTS)查询方法
REQUIRES_NEW开启新的事务挂起外部事务,创建新的事务,新事物完成后再执行外部事物@Transactional(propagation = Propagation.REQUIRES_NEW)日志记录方法中
NOT_SUPPORTED不开启事务挂起外部事务,也不开始新事物@Transactional(propagation = Propagation.NOT_SUPPORTED)及其不常用
NEVER不开启事务抛出异常@Transactional(propagation = Propagation.NEVER)及其不常用
MANDATORY抛出异常融合到外部事务中@Transactional(propagation = Propagation.MANDATORY)及其不常用

4.5只读属性(readOnly)

针对于只进行查询操作的业务方法可以加入只读属性,提高运行效率 不常用

设置readOnly=true开启readOnly 默认值是false
@Transactional(readOnly=true)

4.6超时属性

一个事务等待的最长时间,超出了最长等待时间就会抛出异常

当前事务访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时本事物就必须等待

默认值-1 表示有对应的数据库指定
时间单位: 秒 
@Transactional(timeout=2)

4.7异常属性

Spring在进行事务处理的过程中
默认
  对于RuntimeException及其子类,采用的是回滚策略
  对于Exception及其子类(除了RuntimeException及其子类),采用的是提交的策略
  
使用
   rollbackFor={java.lang.Exception.class,...}  //设置出现那些异常进行回滚处理
   noRollbackFor={xxxException.class}  //设置出现那些异常进行提交处理
  	
  @Transactional(rollbackFor={xxException.class,...},noRollbackFor={xxException.class...})
  	
建议:
   未来实战中,使用默认值即可

4.8事务常见配置总结

1.隔离属性  使用默认值
2.传播属性  增删改(Required默认值) 查询操作——>Supports
3.只读属性 	增删改(false默认值)    查询操作——>true
4.超时属性  使用默认值 -1
5.异常属性  使用默认值

如果是增删改操作 直接使用 @Transactional注解即可,无需指定属性值
如果是查询操作   @Transactional(propagation=Propagation.SUPPORTS,readOnly=true)

5.整合SpringMVC

使用
rollbackFor={java.lang.Exception.class,…} //设置出现那些异常进行回滚处理
noRollbackFor={xxxException.class} //设置出现那些异常进行提交处理

@Transactional(rollbackFor={xxException.class,…},noRollbackFor={xxException.class…})

建议:
未来实战中,使用默认值即可


## 4.8事务常见配置总结

```markdown
1.隔离属性  使用默认值
2.传播属性  增删改(Required默认值) 查询操作——>Supports
3.只读属性 	增删改(false默认值)    查询操作——>true
4.超时属性  使用默认值 -1
5.异常属性  使用默认值

如果是增删改操作 直接使用 @Transactional注解即可,无需指定属性值
如果是查询操作   @Transactional(propagation=Propagation.SUPPORTS,readOnly=true)

5.整合logback

5.1导入依赖

<dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.25</version>
    </dependency>
<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>jcl-over-slf4j</artifactId>
  <version>1.7.25</version>
</dependency>

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.2.3</version>
</dependency>

<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>1.2.3</version>
</dependency>

<dependency>
  <groupId>org.logback-extensions</groupId>
  <artifactId>logback-ext-spring</artifactId>
  <version>0.1.4</version>
</dependency>

5.2配置文件(logback.xml)

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG"> <!--或者info级别-->
        <appender-ref ref="STDOUT" />
    </root>

</configuration>

6.整合SpringMVC

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shstart7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值