Spring-事务

一、在JAVAEE中,事务一般用于Service层(业务逻辑层)

二、在Spring中实现事务管理
(1)编程式事务管理:在方法中利用try-catch捕获异常并处理。
(2)声明式事务管理:通过配置实现。

三、声明式事务管理(基于AOP)
(1)基于注解方式实现。
(2)基于配置文件实现。
(3)Spring提供一个接口,代表事务管理器,针对不同DAO层框架提供不同的实现类。
(4)事务常用参数

  • propagation:事务的传播行为。多个方法进行调用时,如果某些方法配置了事务,Spring怎样实现对事务进行管理。当值为REQUIRED时,所有配置了事务的方法共用一个事务。当值为REQUIRES_NEW时,所有配置了事务的方法都会创建一个事务。
  • isolation:事务的隔离等级。默认为数据库的隔离级别。
  • timeout:事务的超时时间。
  • readOnly:事务是否只允许只读操作。
  • rollbackFor:当出现指定异常时才回滚。
  • noRollbackFor:当出现指定异常时不需要回滚。

四、注解实现(@Transactional)
(1)基于Spring整合Mybatis的环境实现(具体环境见文章Spring整合Mybatis)
(2)添加更新Account中的money功能
Mapper文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wsh.mapper.AccountMapper">
    <select id="selectAccountList" resultType="Account">
        select * from account
    </select>

    <update id="updateAccount">
        update account set money = money + #{arg1} where id = #{arg0}
    </update>
</mapper>

DAO接口

@Mapper
public interface AccountMapper {
    public List<Account> selectAccountList();

    public void updateAccount(Long id, Integer money);
}

Service层接口及实现类

public interface AccountService {
    public List<Account> selectAccountList();

    public void updateAccountTest();
}
@Service
public class AccountServiceImpl implements AccountService{

    @Autowired
    private AccountMapper accountMapper;

    public List<Account> selectAccountList() {
        return accountMapper.selectAccountList();
    }

    @Transactional
    public void updateAccountTest() {
        accountMapper.updateAccount(1L, -100);
        int i = 10 / 0;
        accountMapper.updateAccount(2L, 100);
    }
}

(3)JAVA程序

    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        AccountService accountService = context.getBean("accountServiceImpl", AccountServiceImpl.class);
        accountService.updateAccountTest();
    }

执行前的表数据
1 张三 100
2 李四 100
输出

java.lang.ArithmeticException: / by zero

	at com.wsh.service.AccountServiceImpl.updateAccountTest(AccountServiceImpl.java:31)
	at com.wsh.service.AccountServiceImpl$$FastClassBySpringCGLIB$$2d6e7a30.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.wsh.service.AccountServiceImpl$$EnhancerBySpringCGLIB$$df80911d.updateAccountTest(<generated>)
	at MyTest.test(MyTest.java:23)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
	at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
	at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)


执行后的表数据
1 张三 100
2 李四 100

四、配置文件实现
(1)添加Maven依赖(AOP)

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.2.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>net.sourceforge.cglib</groupId>
            <artifactId>com.springsource.net.sf.cglib</artifactId>
            <version>2.2.0</version>
        </dependency>
        <dependency>
            <groupId>org.aopalliance</groupId>
            <artifactId>com.springsource.org.aopalliance</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>com.springsource.org.aspectj.weaver</artifactId>
            <version>1.6.4.RELEASE</version>
        </dependency>

(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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
       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/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <context:property-placeholder location="classpath:myProperty.properties"></context:property-placeholder>

    <!--数据源-->
    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${my.driver}"></property>
        <property name="url" value="${my.url}"></property>
        <property name="username" value="${my.username}"></property>
        <property name="password" value="${my.password}"></property>
    </bean>

    <!--配置Spring的事务管理器-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"></property>
    </bean>

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

    <!--Spring扫描Dao层下带有注解的接口并为其创建代理对象-->
    <mybatis:scan base-package="com.wsh.mapper"></mybatis:scan>

    <!--开启Spring的组件扫描-->
    <context:component-scan base-package="com.wsh"></context:component-scan>


    <!--配置通知-->
    <tx:advice id="transactionAdvice" transaction-manager="dataSourceTransactionManager">
        <tx:attributes>
            <!--对哪个方法启用事务,可以在该标签配置事务的属性-->
            <tx:method name="updateAccountTest"></tx:method>
        </tx:attributes>
    </tx:advice>

    <aop:config proxy-target-class="true">
        <aop:pointcut id="myPointcut" expression="execution(* com.wsh.service.AccountServiceImpl.*(..))"/>
        <aop:advisor advice-ref="transactionAdvice" pointcut-ref="myPointcut"></aop:advisor>
    </aop:config>
</beans>

(3)JAVA程序

    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        AccountService accountService = context.getBean("accountServiceImpl", AccountServiceImpl.class);
        accountService.updateAccountTest();
    }

注:不需要在方法上用@Transactional注解开始事务

执行前的表数据
1 张三 100
2 李四 100

输出

java.lang.ArithmeticException: / by zero

	at com.wsh.service.AccountServiceImpl.updateAccountTest(AccountServiceImpl.java:30)
	at com.wsh.service.AccountServiceImpl$$FastClassBySpringCGLIB$$2d6e7a30.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:367)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:118)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
	at com.wsh.service.AccountServiceImpl$$EnhancerBySpringCGLIB$$44b03522.updateAccountTest(<generated>)
	at MyTest.test(MyTest.java:23)

执行后的表数据
1 张三 100
2 李四 100

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值