Java学习记录 Spring-事务

本文记录了Spring事务管理的核心概念,包括基于XML和Annotation的两种声明式事务管理方式。详细介绍了PlatformTransactionManager和TransactionDefinition接口,以及在实际应用中如何配置和使用。同时,给出了在xml配置和注解方式下,从实体类到业务处理类的事务管理实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring事务

事务(Transaction)是面向关系型数据库(RDBMS)企业应用程序的重要组成部分,用来确保数据的完整性和一致性。

事务了解 :MySQL学习记录 事务篇

Spring 实现声明式事务管理主要有 2 种方式:

  • 基于 XML 方式的声明式事务管理
  • 通过 Annotation 注解方式的事务管理

事务管理接口

Spring 的事务管理 :PlatformTransactionManager、TransactionDefinition 是事务主要核心接口

PlatformTransactionManager接口

该接口用于管理事务。其主要用于完成事务的提交、回滚,及获取事 务的状态信息

public interface PlatformTransactionManager extends TransactionManager {
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}
返回抽象方法说明
TransactionStatusgetTransaction(@Nullable TransactionDefinition var1)获取事务的状态信息
voidcommit(TransactionStatus var1)提交事务
voidrollback(TransactionStatus var1)回滚事务

TransactionDefinition接口

该接口主要获取事务相关信息的作用

public interface TransactionDefinition {
    ....

    default int getPropagationBehavior() {
        return 0;
    }

    default int getIsolationLevel() {
        return -1;
    }

    default int getTimeout() {
        return -1;
    }

    default boolean isReadOnly() {
        return false;
    }

    @Nullable
    default String getName() {
        return null;
    }
	....
}
返回抽象方法说明
intgetPropagationBehavior()获取事务的 传播行为
intgetIsolationLevel()获取事务的 隔离级别
intgetTimeout()获取事务的 超时时间
booleanisReadOnly()获取事务是否 只读
StringgetName()获取事务的 名称

属性说明

传播行为值说明
PROPAGATION_MANDATORY支持当前事务,如果不存在当前事务,则引发异常
PROPAGATION_NESTED如果当前事务存在,则在嵌套事务中执行
PROPAGATION_NEVER不支持当前事务,如果当前事务存在,则引发异常
PROPAGATION_NOT_SUPPORTED不支持当前事务,始终以非事务方式执行
PROPAGATION_REQUIRED默认传播行为,支持当前事务,如果不存在,则创建一个新的
PROPAGATION_REQUIRES_NEW创建新事务,如果已经存在事务则暂停当前事务
PROPAGATION_SUPPORTS支持当前事务,如果不存在事务,则以非事务方式执行

xml应用

主要配置组件(.xml)

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <!--            <tx:method name="insert*" propagation="REQUIRED"/>-->
        <!--            <tx:method name="add*" propagation="REQUIRED"/>-->
        <!--            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>
<!--   aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
    <aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
    <aop:advisor advice-ref="txAdvice"  pointcut-ref="pt" />
</aop:config>

应用前提:

添加依赖

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

实体类:(Student)

package com;

public class Student {
    int id ;
    String name;
    int age;
    
    public Student() {
    }
    
    public Student(int id , String name , int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    public Student(String name , int age) {
        this.name = name;
        this.age = age;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

StudentDao类:(信息交互类)

package com.dao;

import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class StudentDao extends JdbcDaoSupport {
    
    /**
     * 添加数据
     * @param student 学生类封装
     * @return 更变条数
     */
    public int insert(Student student) {
        if (student == null) {
            return 0;
        }
        String sql = "insert into student(name,age) value(?,?)";
        return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
    }
    
    //其他业务操作省略
    ····
}

StudentService类:(业务处理类)

package com.service;

import com.Student;
import com.dao.StudentDao;

public class StudentService {
    
    private StudentDao studentDao;
    
    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }
    
    public int insert(Student student){
        int a = studentDao.insert(student);
        System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
        int aa = 1/0;   //制造异常
        student.setAge(student.getAge()+1);
        int b = studentDao.insert(student);
        System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
        return a+b;
    }
}

Spring 容器配置:(.xml文件)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/tx 
			http://www.springframework.org/schema/tx/spring-tx.xsd
			http://www.springframework.org/schema/aop 
			http://www.springframework.org/schema/aop/spring-aop.xsd
">

    <!--    XML 配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl"
                  value="jdbc:mysql://192.168.6.129:3306/test?serverTimezone=UTC&amp;characterEncoding=utf8&amp;useUnicode=true&amp;useSSL=false"/>
        <property name="user" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--    配置jdbc模板-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--    类注入应用-->
    <bean id="studentDao" class="com.dao.StudentDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
    <bean id="studentService" class="com.service.StudentService">
        <property name="studentDao" ref="studentDao"/>
    </bean>

    <!--    事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!--    事务触发方法 以及 事务处理方式-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--            <tx:method name="insert*" propagation="REQUIRED"/>-->
            <!--            <tx:method name="add*" propagation="REQUIRED"/>-->
            <!--            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>-->
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>
    <!--   aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 -->
    <aop:config>
        <aop:pointcut id="pt" expression="execution(* com.service..*.*(..))"/>
        <aop:advisor advice-ref="txAdvice"  pointcut-ref="pt" />
    </aop:config>

</beans>

测试:

@Test
public void test_XML(){
    
    ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig.xml");
   
    StudentService service = (StudentService) ac.getBean("studentService");
    
    //在studentService类 会异常回滚 
    int number = service.insert(new Student("李四" , 33));
    System.out.println("number : " + number);

}

Annotation应用

主要组件

@Transactional

@Transactional常用属性

属性名说明
propagation配置 事务传播行为
isolation配置 事务隔离级别
readOnly配置 事务是否只读
timeout配置 事务超时事件(单位: s)

应用前提:

  • 注册加载驱动

    <tx:annotation-driven transaction-manager="txManager"/>
    
  • 应用方法需要添加 @Transactional 注解

实体类:(Student)

package com;

public class Student {
    int id ;
    String name;
    int age;
    
    public Student() {
    }
    
    public Student(int id , String name , int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    
    public Student(String name , int age) {
        this.name = name;
        this.age = age;
    }
    
    public int getAge() {
        return age;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

StudentDao类:(信息交互类)

package com.dao;

import com.Student;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class StudentDao extends JdbcDaoSupport {
    
    /**
     * 添加数据
     * @param student 学生类封装
     * @return 更变条数
     */
    public int insert(Student student) {
        if (student == null) {
            return 0;
        }
        String sql = "insert into student(name,age) value(?,?)";
        return this.getJdbcTemplate().update(sql,student.getName(),student.getAge());
    }
    
    //其他业务操作省略
    ····
}

StudentService类:(业务处理类)

package com.service;

import com.Student;
import com.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class StudentService {
    
    //注入类
    @Autowired
    private StudentDao studentDao;
    
    //事务配置
    @Transactional(propagation = Propagation.REQUIRED , rollbackFor = {Exception.class})
    public int insert(Student student){
        int a = studentDao.insert(student);
        System.out.println("(1)添加成功 数据: " + student + "\t影响条目:"+a);
        
        int aa = 1/0;   //制造异常
        
        student.setAge(student.getAge()+1);
        int b = studentDao.insert(student);
        System.out.println("(2)添加成功 数据: " + student + "\t影响条目:"+a);
        return a+b;
    }
    
}

Spring 容器配置:(.xml文件)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       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/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
">

    <!--    XML 配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <!--驱动加载-->
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <!--连接数据库的url  . 本次连接 test库-->
        <property name="url" value="jdbc:mysql://192.168.6.129/test"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
    <!--    配置jdbc模板-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <!--必须使用数据源-->
        <property name="dataSource" ref="dataSource"/>
    </bean>
	
    <!--扫描包-->
    <context:component-scan base-package="com"/>
<!--    事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
<!--    事务应用-->
    <bean id="studentDao" class="com.dao.StudentDao">
        <property name="jdbcTemplate" ref="jdbcTemplate"/>
    </bean>
	<!--以注解形式应用-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

测试:

 @Test
public void test_Annotation() {
    ApplicationContext ac = new ClassPathXmlApplicationContext("SpringConfig_Annotation.xml");
    StudentServic service = (StudentService) ac.getBean("");

    int number = service_annotation.insert(new Student("赵六" , 34));
    System.out.println("number : " + number);
    
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值