spring学习

1 spring简介

1.1 官网API:

https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-p-namespace

1.2 控制反转:

将组件对象的控制权由代码本身转移到外部容器。发现传统方式,如果切换了实现类就必须在代码中更改实现类,这种方式就是耦合度很高,违反了spring的思想,组件化配置。

2 spring程序开发

2.1 添加依赖 spring-webmvc

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.6</version>
</dependency>`

2.2 创建核心配置文件

<?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">
</beans>

2.3 在spring配置文件中配置userdaoimpl

<bean id="usreMapper" class="cn.hxzy.dao.impl.UserMapperImpl"></bean>

2.4 使用spring的API获得bean的实例

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
public boolean save() {
    UserMapper userMapper = (UserMapper) context.getBean("userMapper");
    Integer count = userMapper.save();
    if (count > 0) {
        return true;
    }
    return false;
}

3 依赖注入

3.1 构造方法注入

3.1.1 按照构造函数的参数索引值位置进行注入
<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg index="0" value="zhangsan"/>
    <constructor-arg index="1" value="20"/>
</bean>
3.1.2 按照构造函数的参数进行注入

注意,如果按类型进行匹配注入,配置的是基本数据类型,则在class中定义的属性也必须为基本数据类型。如果为包装类,定义的时候也必须为包装类型

<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg type="java.lang.String" value="lisi"/>
    <constructor-arg type="java.lang.Integer" value="24"/>
</bean>

bean标签的作用范围

singleton默认的,单例的
prototype多例的
requestSpringWeb应用中,创建一个bean对象后,存入到request作用域
sessionSpringWeb应用中,创建一个bean对象后,存入到sessiont作用域
3.1.3 引入注入
<bean id="user" class="cn.hxzy.pojo.User">
    <constructor-arg index="0" value="zhangsan"/>
    <constructor-arg index="1" value="20"/>
    <constructor-arg ref="dog"/>
</bean>
<bean id="dog" class="cn.hxzy.pojo.Dog">
    <constructor-arg index="0" value="旺财"/>
    <constructor-arg index="1" value="3"/>
</bean>

3.2 设值注入

3.2.1 properties属性注入

setter器

public void setUserName(String userName) {
     this.userName = userName;
}

xml配置

<bean id="stu" class="cn.hxzy.pojo.Student">
    <property name="userName" value="qyy"/>
</bean>
3.2.2 p-namespace p命名空间注入

配置的头文件引用

xmlns:p="http://www.springframework.org/schema/p"

3.3 注入复杂数据类型

<bean id="data" class="cn.hxzy.news.test.DataCategroy">
    <property name="strs">
        <array>
            <value>html</value>
            <value>vue</value>
            <value>spring</value>
        </array>
    </property>
    <property name="list">
        <list>
            <value>java</value>
            <value>jdbc</value>
            <value>maven</value>
        </list>
    </property>
    <property name="map">
        <map>
            <entry key="ch" value="中国"/>
            <entry key="en" value="英国" />
            <entry key="us" value="美国"/>
            <entry key="ru" value="俄罗斯"/>
        </map>
    </property>
</bean>

4 bean的自动装配方式

<bean id="user" class="cn.hxzy.pojo.User" autowire="byName">
    <property name="userName" value="zhangsan"/>
    <property name="userAge" value="30"/>
    <property name="userId" value="100"/>
</bean>
<bean id="dog" class="cn.hxzy.pojo.Dog">
    <property name="dogColor" value="黄色"/>
    <property name="dogName" value="旺财"/>
</bean>

byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid。
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean,如果在容器存在相同类型的对象,则不能使用byType。

使用Java的注解也必须在spring配置文件中配置context约束

@Resource与@Autowired的区别:
@Resource是java的注解,默认是按照名称进行装配,相当于是@Autowired加@Qualifier(value = "user")的合体
@Autowired是spring的注解,默认是按照类型进行装配

相同点
   都是用来自动装配的,都可以放在属性字段上
不同点
    @Autowired通过byType的方式实现,必须要求这个对象存在
    @Resource默认通过byName的方式实现,如果找不到名字,则通过byType实现。

5 使用注解自动装配

5.1 编写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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
</beans>

5.2 配置注解支持

<context:annotation-config/>

5.3 自动扫描标注注解的包

<!--在容器启动的时候,对标注注解的包进行自动扫描,扫描到以后自动进行注册到容器-->
<context:component-scan base-package="cn.hxzy"/>

5.4 常用注解的说明

@Component //相当于在spring配置文件中定义的bean节点,当容器加载的时候,扫描包以后就会进行注册到IOC容器
根据@Component注解衍生出一些注解:
@Repository 代表数据访问层
@Service 代表业务逻辑层, 通常情况会给他加名称 @Service(value = “userService”)
@Controller 代表控制层
@Autowired 注解实现的bean的自动装配,默认是按照类型去装配的,如果容器中出现了两个类型相同的bean,则需要添加注解
@Qualifier(value = “jdbcMysqlDao”)//根据名称来自动装配
@Resource是java自己的注解,默认按照名称来自动装配,如果该bean没有名称,则按照类型进行装配
@Configration 相当于spring核心配置文件里面的beans
@Bean:用于@Configration配置类中,声明一个对象让spring容器管理,一般用于整合其他框架后,把它的类注册为bean实例对象后供spring来调度使用的。
@PropertySource(“classpath:application.properties”)读取静态资源目录下指定名称的properties文件
@Value(“${name}”)

@Bean与 @Component的区别:
两者都是Spring框架中用于定义bean的注解,但它们的用途和范围有所不同。以下是两者的区别:

作用对象不同:@Bean注解作用于方法,用于显式声明单个bean,而@Component注解作用于类,用于自动检测和使用类路径扫描自动配置bean。

配置方式不同:@Bean注解通常与@Configuration注解一起使用,允许开发者精确地创建和配置bean,提供更多关于bean的配置信息,如初始化方法、作用域、命名等;@Component注解则更多用于自动装配到Spring容器中,适用于简单的业务类。

使用场景不同:@Bean适用于需要更精细控制的bean配置,如第三方库中的类;@Component适用于简单的业务类或组件。

总结来说,如果需要简单地将一个类声明为bean,可以使用@Component;如果需要详细配置bean或从方法中产生bean,则应使用@Bean。

6 aop的简介

AOP是面向切面编程的意思,全称为Aspect Oriented Programing。
他是一种基于OOP之上的一种编程范式,弥补了OOP的不足,能更好的组织程序结构。
AOP可以把业务的功能步骤做成插拔式的组件,从而可以用这些组件定制新的功能,因此AOP可以提高业务的复用性,提高开发效率。把现有的代码做增强处理。

7 代理模式

7.1 代理模式的好处

可以使真实角色的操作更加存粹,不用去关注一些公共的业务。
公共业务就交给了代理角色,实现了业务的分工。
公共业务发生扩展的时候,方面集中管理。

8 spring使用aop

8.1 aop的的一些相关名词

  • 切面(Aspect):横切关注点被模块化的特殊对象,是一个类,里面可以定义切入点和通知(切面 = 切点+通知)
  • 通知(Advice):切面必须要完成的工作,是类中的一个方法
  • 切入点(pointCut):切面通知执行的位置
  • 连接点(JointPoint):程序执行过程中明确的点,一般是方法的调用

8.2 引入依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>

8.3 在核心配置文件中导入aspectj约束

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

8.4 定义一个日志类

8.4.1 前置通知
@Component("beforeLog")
public class LoggerProgram implements MethodBeforeAdvice {

    /**
     * 前置增强
     * @param method  执行的目标方法
     * @param objects  参数列表数组,如果目标方法无参,则为null
     * @param o 目标对象
     * @throws Throwable
     */
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("执行方法的当前时间为:"+ LocalDateTime.now());
        System.out.println("目标对象的方法名称为:"+method.getName());
        System.out.println("方法的参数为:");
        for (Object object : objects) {
            System.out.println(object);
        }
        System.out.println("目标对象的类型为:"+o.getClass().getName());
    }
}
8.4.2 后置通知
@Component("afterLog")
public class LoggerAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行方法完成的时间为:"+ LocalDateTime.now());
        System.out.println("目标对象的方法名称为:"+method.getName());
        System.out.println("方法的参数为:");
        for (Object object : objects) {
            System.out.println(object);
        }
        System.out.println("目标对象的类型为:"+o1.getClass().getName());
        System.out.println("方法的返回值为:"+o);
    }
}
8.4.3 环绕通知
@Component("around")
public class AroundTest implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {

        System.out.println("方法开始执行,时间为:" + LocalDateTime.now());
        long start = System.currentTimeMillis(); //系统时间戳 1970.1.1
        
        Object rs=methodInvocation.proceed(); //目标方法进行调用执行
        
        System.out.println("方法执行完成,时间为:" + LocalDateTime.now());
        long end = System.currentTimeMillis();
        System.out.println("所用时间为:" + (end - start));
        System.out.println("方法的返回值为:"+rs);
        return rs; //方法的返回值
    }

}

8.5 在核心配置文件中加入aop配置

<!--aop:xml的配置-->
<aop:config>
    <!--定义切入点-->
    <aop:pointcut id="point" expression="execution(* cn.hxzy.dao.impl.*.*(..))"/>
    <!--定义通知-->
    <!--<aop:advisor advice-ref="beforeLog" pointcut-ref="point"/>-->
    <aop:advisor advice-ref="afterLog" pointcut-ref="point"/>
</aop:config>

通知类型:
前置通知:方法执行前进行的代码编织,xml配置实现接口:MethdBeforeAdvice。
后置通知:方法执行后进行的代码编织 xml配置实现接口:AfterReturningAdvice。
环绕通知:方法执行前后都进行代码编织,区别于前置+后置。把目标方法进行了围绕,无论是否发生异常都会被执行。xml配置实现接口:MethodInterceptor。

切入点表达式:
execution(* cn.hxzy.dao.impl.*.*(..))
第一个* 表示的是方法任意的返回值
第二个* 表示任意的类
最后一个*表示的是任意的方法

9 使用注解来定义切面

好处:1、增加了代码的灵活度  2、减少了配置代码量

使用@Aspect,首先要保证所用的JDK 是5.0或以上版本

@Aspect 标注这个类是一个切面

@Before("execution(* cn.hxzy.dao.Impl.UserDaoImpl.*(..))") 前置通知

@AfterReturning("execution(*cn.hxzy.dao.Impl.UserDaoImpl.*(..))") 后置通知

@AfterThrowing 异常通知, 在方法抛出异常之后

@Around 环绕通知, 围绕着方法执行

@After 最终增强
<!---开启aspectj框架的自动代理-->
<aop:aspectj-autoproxy expose-proxy="true" />

注解示例

@Aspect
@Component
public class AdviceLog {

    @Pointcut("execution(* cn.hxzy.dao.impl.*.*(..))")
    public void pt(){}

    //前置通知
    @Before("AdviceLog.pt()")
    public void beforeLog(JoinPoint joinPoint) {
        //得到代理对象的签名信息
        Signature signature = joinPoint.getSignature();
        Class c1 = signature.getDeclaringType();
        System.out.println("方法名:" + signature.getName());
        System.out.println("类名:" + c1.getName());
        System.out.println("参数信息:");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println(arg);
        }
    }

    //后置通知
    @AfterReturning(returning = "result", pointcut = "AdviceLog.pt()")
    public void afterLog(JoinPoint joinPoint, Object result) {
        System.out.println("方法执行完毕后的时间为:" + LocalDateTime.now());
        System.out.println("方法的执行返回结果为:" + result);
    }

    //环绕通知
    @Around("AdviceLog.pt()")
    public Object around(ProceedingJoinPoint joinPoint) {
        System.out.println("方法开始执行,时间为:" + LocalDateTime.now());
        long start = System.currentTimeMillis(); //系统时间戳 1970.1.1
        //调用方法本身去执行
        Object result = 0;
        try {
            result = joinPoint.proceed();  //调用方法....
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("所用时间为:" + (end - start));
        System.out.println("方法的返回值为:" + result);
        return result;
    }

}

10 spring集成Mybatis

1、IOC spring创建对象,给对象的属性赋值,完成对对象的管理。
2、AOP 在不影响核心业务代码的基础上,把公共的一部分基础业务,抽取到切面中,然后在程序的编译器(运行期)通过代理的方式,实现代码的织入。

导入依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId> 
    <version>2.0.6</version>
</dependency>

10.1 什么是 MyBatis-Spring

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

spring整合mybatis的步骤:

10.2 导入依赖

<dependencies>
    <!-- junit测试包 -->
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
    
    <!-- mybatis-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>

    <!-- mysql驱动包 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.29</version>
    </dependency>

    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.20</version>
        <scope>provided</scope>
    </dependency>

    <!-- Spring 相关-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.8</version>
    </dependency>
    
    
    <!-- spring 操作jdbc-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.3.8</version>
    </dependency>


    <!--AOP相关-->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7.M3</version>
    </dependency>

    <!--mybatis整合spring的补丁包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.0.6</version>
    </dependency>

    <!--阿里巴巴的数据源连接池-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.18</version>
    </dependency>
    
</dependencies>

10.3 创建maven集成的mybatis项目

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:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.2.xsd">
</beans>

mybatis的核心配置文件

<?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">
<!--mybatis的核心配置文件-->
<configuration>
    <settings>
        <!--全局开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <setting name="autoMappingBehavior" value="FULL"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <package name="cn.hxzy.pojo"/>
    </typeAliases>

    <!--注册  映射器-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"></mapper>
    </mappers>
</configuration>

10.4 编写了数据源druid.properties

druid.driver=com.mysql.jdbc.Driver
druid.url=jdbc:mysql://localhost:3306/ticket?serverTimezone=UTC&useUnicode=true&useSSL=false&characterEncoding=utf8
druid.username=root
druid.password=root

druid.pool.init=5
druid.pool.minIdle=5
druid.pool.maxActive=100
druid.pool.maxWait=30000

10.5 编写了spring的核心配置文件

读取数据源

<!--spring读取properties文件-->
<context:property-placeholder location="classpath:druid.properties"/>

<!--数据源连接池-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="${druid.driver}"/>
    <property name="url" value="${druid.url}"/>
    <property name="username" value="${druid.username}"/>
    <property name="password" value="${druid.password}"/>
    <property name="initialSize" value="${druid.pool.init}"/>
    <property name="minIdle" value="${druid.pool.minIdle}"/>
    <property name="maxActive" value="${druid.pool.maxActive}"/>
    <property name="maxWait" value="${druid.pool.maxWait}"/>
</bean>

注册sqlSessionFactoryBean

<!--Spring注册SqlSessionFactory对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="druidDataSource"/>
    <property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>

实例对象

<!--newsMapper的bean实例对象-->
<bean id="newsMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    <property name="sqlSessionTemplate" ref="sqlSession"/>
    <property name="mapperInterface" value="cn.hxzy.mapper.NewsMapper"/>
</bean>

此方法也可以简写为:
指定扫描基准包,把包下面面的接口注册成spring容器所管理的接口对象

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.hxzy.dao"/>
</bean>
<context:annotation-config />
<context:component-scan base-package="cn.hxzy"/>
<aop:aspectj-autoproxy expose-proxy="true"/>

11 声明式事务

事务的概念:把一组SQL指令打包一个独立的语句模块执行,如果里面有任意一条语句执行失败,则整个语句执行操作都将会回滚。
四个特性:1、原子性 2、持久性 3、隔离性 4、一致性

原子性:一组sql,一批sql是一个最小的执行单元,不可分割
持久性:执行命名令后,产生的结果是永久性的,不可逆转。
隔离性:两个及以上的并发事务执行的时候,互不影响
一致性:事务执行前后,对数据的操作产生的影响是一致的。

11.1 事务管理器的配置

<!-- 定义事务管理器-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="druidDataSource"/>
</bean>
<!--配置切点,引用通知-->
<aop:config>
    <aop:pointcut id="mypoint" expression="execution(* cn.hxzy.service.impl.*.*(..))"/>
    <aop:advisor  advice-ref="myAdvice" pointcut-ref="mypoint"/>
</aop:config>
<!--通知-->
<tx:advice transaction-manager="txManager" id="myAdive">
    <!--事务规则-->
    <tx:attributes>
        <tx:method name="zhuanZhang" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="insert*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

11.2 事务的隔离级别

描述的是两个及以上的并发事务,执行的过程中,针对事务之间的互相影响的情况的一种应对策略。
并发事务可能出现的问题:
脏读:事务1执行的过程中,事务2读取到了事务1修改过但还未提交的数据,这种情况就叫做脏读。

不可重复度:事务1先后读取同一条记录,但两次读取的数据不同,原因是在这之间事务2进行数据的修改,并提交,导致事务1两次读取到的数据不同,称之为不可重复读

幻读:事务1按照条件查询数据时,没有对应的数据行,在这期间,事务2插入了对应的数据行,并且进行了提交,之后事务1在插入对应的数据时,又发现这行数据已经存在,好像出现了幻觉。

DEFAULT :采用的JDBC的隔离级别

4==SERIALIZABLE 串行化:   T1在执行的过程中,T2既不能读与不能写

3=REPEATABLE_READ 可重复读(mysql):T1在执行的过程中,T2只读与不能修改数据,T2可以添加数据,可能会导致T1幻读   (幻读)

2=READ_COMMITTED 读已提交 (oracle):T1在执行的过程中,T2可以读也可以写,但是T1只能读取到T2提交后的数据(幻读)(不可重复读)

1=READ_UNCOMMITTED 读未提交:T1在执行的过程中,T2可以读也可以写,T1可以读取到T2未提交的数据(幻读)(不可重复读)(脏读)

11.3 事务的传播机制

REQUIRED:     如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则加入到事务中。

SUPPORTS:  如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则加入到事务中。

REQUIRES_NEW: 如果上层方法没有事务,则创建一个新的事务。如果已经存在事务,则将当前事务挂起,创建新事务执行。

NOT_SUPPORTED:如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则将当前事务挂起,以非事务方式执行。

NEVER: 如果上层方法没有事务,则以非事务方式执行。如果已经存在事务,则将当前事务挂起,并抛出异常。

MANDATORY: 如果上层方法没有事务,则抛出异常,如果已经存在事务,则加入到事务重执行。

NESTED:如果上层方法没有事务,则创建一个新的事务,如果已经存在事务,则嵌套到当前事务中。

11.4 事务的其他属性

timeout:事务超时时间,允许事务运行的最长时间,以秒为单位。默认值为-1,表示不超时

read-only:事务是否为只读,默认值为false

rollback-for:设定能够触发回滚的异常类型、Spring默认只在抛出runtime exception时才标识事务回滚、可以通过全限定类名指定需要回滚事务的异常,多个类名用逗号隔开

no-rollback-for:设定不触发回滚的异常类型、Spring默认checked Exception不会触发事务回滚、可以通过全限定类名指定不需回滚事务的异常,多个类名用英文逗号隔开

11.5 使用注解的形式实现声明式事务的配置

可以直接配置在类上或者方法上

@Service
@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRES_NEW,noRollbackFor = ArithmeticException.class)
public class TransferAccountServiceImpl implements TransferAccountService {
    
}

也可以叫灵活的配置在所需要的方法上

@Transactional(isolation = Isolation.REPEATABLE_READ,propagation = Propagation.REQUIRES_NEW,noRollbackFor = ArithmeticException.class)
public boolean transferAccount(int fromUserId, int toUserId, double money) {
     
}

在配置文件中添加上,注解事务的支持

<!--启动注解方式的支持-->
<tx:annotation-driven transaction-manager="txManager"/>
  • 31
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值