为了账号安全,请及时绑定邮箱和手机立即绑定

Spring(四):事务管理

标签:
Java Spring

事务

首先,我们要知道事务是什么

构成单一逻辑工作单元的操作集合称为事务

事务的ACID特性

  • 原子性:不可分割的最小操作单位,要么同时成功,要么同时失败

  • 一致性:事务操作前后,数据总量不变

  • 隔离性:多个事务之间相互独立

  • 持久性:当事务提交或回滚后,数据会持久化的保存数据

传统编程的事务管理

在传统的JAVA数据库编程中,我们遵循的是打开连接-执行操作-提交事务-关闭连接,如下面的代码:


Connection  con = getCon();

con.setAutoCommit(false);

con.prepareStatement("UPDATE...").execute();

con.prepareStatement("UPDATE...").execute();

con.commit();

//conn.rollback();

con.close();

这样就产生了很多模板代码,而且依靠程序员手动提交事务,也十分不可靠

Spring对事务的管理

Spring的事务管理分为两类

  • 声明式事务

  • 编程式事务

Spring定义了一个接口PlatformTransactionManager,我们只需要使用其实现类,将数据源交其管理,即可实现Spring事务管理


@Configuration

@EnableTransactionManagement  // 开启事务管理

@ComponentScan("wang.ismy.spring")

public  class  Config {

  

@Bean

public  DataSource  dataSource(){

DruidDataSource  druidDataSource = new  DruidDataSource();

druidDataSource.setUrl("jdbc:mysql:///test");

druidDataSource.setUsername("root");

druidDataSource.setPassword("123");

return druidDataSource;

}

  

@Bean

public  JdbcTemplate  jdbcTemplate(DataSource  dataSource){

return  new  JdbcTemplate(dataSource);

}

  

@Bean

public  PlatformTransactionManager  transactionManager(DataSource  dataSource){

return  new  DataSourceTransactionManager(dataSource);

}

}

这样,当你在你的service中抛出异常的时候,Spring就会自动帮你进行事务回滚


@Transactional(rollbackFor = Exception.class) // Spring默认只对运行期异常回滚,加上该属性,则设置回滚的异常类型为Exception

public  void  transfer() {

  

jdbcTemplate.execute("UPDATE account SET amount = 90 WHERE name = 'alice'");

int  a=1/0;

jdbcTemplate.execute("UPDATE account SET amount = 110 WHERE name = 'bob'");

  

}

属性

@Transactional注解的一些属性说明如下

  • read-only:是否是只读事务。默认false,不只读。

  • isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。

  • propagation:指定事务的传播行为。

  • timeout:指定超时时间。默认值为:-1。永不超时。

  • rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。没有默认值,任何异常都回滚。

  • no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚。没有默认值,任何异常都回滚。

理解事务的传播行为

  • PROPAGATION_REQUIRED

简单来说就是两个被事务管理的方法都将在同一个事务内执行

  • PROPAGATION_REQUIRES_NEW

而这个传播行为则是开启一个新事务

  • PROPAGATION_NESTED

该传播行为则是与JDBC的保存点一样,它使用了物理事务的保存点的概念

编程式事务

一般来说,编程式事务很少用,它就是把一些对数据库的更新操作放在一起,来达到事务管理的目的

首先,我们需要一个


@Bean

public  TransactionTemplate  transactionTemplate(PlatformTransactionManager manager){

return  new  TransactionTemplate(manager);

}

在使用的时候注入这个Template进行操作


public  void  transfer(){

transactionTemplate.execute((TransactionCallback<Void>) status -> {

String  sql = "UPDATE account SET money = money -200 WHERE uid = 41";

String  sql1 = "UPDATE account SET money = money +200 WHERE uid = 45";

jdbcTemplate.update(sql);

jdbcTemplate.update(sql1);

return  null;

});

}

这样,也能进行事务管理

原理

最后,来探讨一下Spring事务管理的原理

一句话,事务管理是通过AOP实现的,这个我们通过获取Bean的实际类型就知道


System.out.println(context.getBean(AccountService.class).getClass());

// 结果:class wang.ismy.spring.AccountService$$EnhancerBySpringCGLIB$$f8bd6705

这是Spring官网给出的一个受事务管理的概念视图:

AOP增强了我们的Service类,当真实的方法被调用前与调用后,Spring替我们完成commit/rollback等操作,以实现事务管理

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消