Spring对事务的支持

Spring对事务的支持

对事务的支持无论是基于xml配置还是基于注解形式 底层原理都是通过AOP环绕增强的方式实现的,特点都是不改变原有的代码逻辑

数据库表格:
在这里插入图片描述
目的是:张三给李四转50时采用事务保证数据的可靠性,不会因为程序运行期错误导致转账出现问题

1.项目案例

  1. 创建MoneyDao接口及实现类并注入到Spring容器中
@Repository
public class MoneyDaoImpl implements MoneyDao {

    @Autowired
    private JdbcTemplate template;

    @Override
    public void tranceOut(String name, Integer count) {
        template.update("update  money set money=money-? where `name` =? ",count,name);

    }

    @Override
    public void tranceIn(String name, Integer count) {
        template.update("update  money set money=money+? where `name` =? ",count,name);
    }
}
  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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--将dao添加到Spring容器中-->
    <context:component-scan base-package="com.example.dao com.example.service"></context:component-scan>
    <!--加载配置文件-->
    <context:property-placeholder location="classpath:com/example/jdbc-config.properties"></context:property-placeholder>
    <!--放置连接池对象-->
    <bean name="database" class="com.alibaba.druid.pool.DruidDataSource">
        <!--将配置文件参数传入连接池-->
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
    </bean>
    <!--将Spring支持的jdbcTemplate放入容器中-->
    <bean name="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="database" ></constructor-arg>
    </bean>

</beans>
  1. 创建外部连接池配置文件
    jdbc-config.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///temporary?useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=12345
  1. 创建service接口及实现类并注入到Spring容器中
@Service
public class MoneyServiceImpl implements MoneyService {
    @Autowired
    private MoneyDao moneyDao;
    @Override
    public void thrance(String out, String in, Integer count) {
        moneyDao.tranceOut(out,count);
        int a = 10/0;  //这里模拟运行期异常
        moneyDao.tranceIn(in,count);
    }
}
  1. 创建test类
@RunWith(SpringRunner.class)
@ContextConfiguration("classpath:com/example/spring/spring-jdbc.xml")
public class TestDemo3 {
    @Autowired
    private MoneyService moneyService;
    //测试增加
    @Test
    public void testTrance(){
       moneyService.thrance("张三","李四",50);
    }

}
  1. 显示结果
    在这里插入图片描述
    张三的钱数少了,但是李四的钱数没有增加,这样的结果就是需要增加事务管理,防止数据出错

1.基于XML配置

  1. 核心对象 平台事务管理器(PlatformTransactionManager)
  • 基于JDBC事务的实现: DataSourceTransactionManager
  • 将它注册到Spring 容器中。
    <!--事务管理器-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="database"></property>
    </bean>
  1. 使用事务的标签开启事务
    <!--设置事务增强-->
    <tx:advice id = "txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--设置想要事务管理的方法名,并设置事务权限-->
            <tx:method name="thrance" read-only="false"/>
        </tx:attributes>
    </tx:advice>
  1. 使用AOP配置指定增强的方法
    <aop:config>
     	<!--表达式中第一个*表示返回值类型,中间用空格隔开-->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.example.service.impl.*ServiceImpl.*(..))"></aop:advisor>
    </aop:config>
  1. 使用另一种从容器中获取Bean的方式测试
public class Demo3 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                "classpath:com/example/spring/spring-jdbc.xml");
        MoneyService moneyService = (MoneyService) context.getBean("moneyServiceImpl");
        moneyService.thrance("张三","李四",50);
    }
}
  1. 测试结果:
    数据不变,并且程序报错
    在这里插入图片描述

2.基于注解配置

  • 在需要进行事务控制的类上(Service实现类)使用注解: @Transactional
    • 此注解既可以使用在类上,也可以使用在方法上,
    • 加在类上表示所有的方法都被事务管理
    • 加在方法上表示只有该方法被事务管理
@Service
@Transactional
public class MoneyServiceImpl implements MoneyService {
    @Autowired
    private MoneyDao moneyDao;
    @Override
    public void thrance(String out, String in, Integer count) {
        moneyDao.tranceOut(out,count);
        int a = 10/0;
        moneyDao.tranceIn(in,count);
    }
}
  • 在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" xmlns:tx="http://www.springframework.org/schema/tx"
       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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
    <!--将dao添加到Spring容器中-->
    <context:component-scan base-package="com.example.dao com.example.service"></context:component-scan>
    <!--加载配置文件-->
    <context:property-placeholder location="classpath:com/example/jdbc-config.properties"></context:property-placeholder>
    <!--放置连接池对象-->
    <bean name="database" class="com.alibaba.druid.pool.DruidDataSource">
        <!--将配置文件参数传入连接池-->
        <property name="driverClassName" value="${jdbc.driverClassName}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
        <property name="url" value="${jdbc.url}"></property>
    </bean>
    <!--将Spring支持的jdbcTemplate放入容器中-->
    <bean name="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="database" ></constructor-arg>
    </bean>

    <!--事务管理器-->
    <bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="database"></property>
    </bean>
    <!--开启事务驱动-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>

一般为了简化xml配置文件会将连接池的配置单独放在一个xml中,然后在这个里面进行引入import

在类上或者方法上加@Transactional可以设置readOnly属性:
@Transactional(readOnly = false)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值