mysql的事物传播机制_Spring之事务管理,事务传播机制(JavaConfig方式)

一、事务的特性

1、 原子性(Atomicity):原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

2、一致性(Consistency):一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。拿转账来说,假设用户A和用户B两者的钱加起来一共是1000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是1000,这就是事务的一致性。

3、隔离性(Isolation):隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

4、持久性(Durability):持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

二、Spring中的事务

1、 Spring对事务有两种支持

①编程式事务:通过DataSourceTransactionManager 获得TransactionStatus 手动commit、rollback。(相信很少有人用把)

②声明式事务:Spring通过aop技术对事务进行管理,我们只需要简单的配置,就可以。有xml方式和注解方式。

2、JavaConfig方式

①通过@EnableTransactionManagement开启事务管理

@Configuration

@ComponentScan(basePackages = "com.caofanqi")

@EnableTransactionManagement //启动事务管理

@Import(DataSourceConfig.class)

public class JavaConfig {

}

②配置Druid数据库连接池

@Configuration

@PropertySource("classpath:jdbc.properties")

public class DataSourceConfig {

@Value("${jdbc.driver}")

private String driverClassName;

@Value("${jdbc.url}")

private String jdbcUrl;

@Value("${jdbc.username}")

private String username;

@Value("${jdbc.password}")

private String password;

/**

* Druid数据库连接池配置

*/

@Bean

public DruidDataSource dataSource() throws SQLException {

DruidDataSource ds = new DruidDataSource();

/**

* 基本属性

*/

ds.setDriverClassName(driverClassName);

ds.setUrl(jdbcUrl);

ds.setUsername(username);

ds.setPassword(password);

/**

* 配置初始化大小、最小、最大

* 通常来说,只需要修改initialSize、minIdle、maxActive

*/

ds.setInitialSize(2);

ds.setMinIdle(2);

ds.setMaxActive(20);

ds.setTestWhileIdle(true);

/**

* 配置获取连接等待超时的时间

*/

ds.setMaxWait(5000);

/**

* 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒

*/

ds.setTimeBetweenEvictionRunsMillis(60000);

/**

* 配置一个连接在池中最小生存的时间,单位是毫秒

*/

ds.setMinEvictableIdleTimeMillis(30000);

return ds;

}

/**

* 事务管理器

*/

@Bean

public DataSourceTransactionManager dataSourceTransactionManager() throws SQLException {

return new DataSourceTransactionManager(dataSource());

}

/**

* 使用JDBC模板

*/

@Bean

public JdbcTemplate jdbcTemplate(DruidDataSource druidDataSource) throws SQLException {

return new JdbcTemplate(druidDataSource);

}

}

③现在我们只需要在Service层需要使用到事务的方法上添加@Transactional注解就好了

@Service

public class UserServiceImpl implements UserService {

@Autowired

private UserDao userDao;

@Transactional

public void add(User user) {

userDao.addUser(user.getName(),user.getAge());

int i = 1/0;//故意制造一个错误,看一下事务是否生效了

}

}

④测试代码:

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(classes = JavaConfig.class)

public class UserServiceTest {

@Autowired

private UserService userService;

@Test

public void testAdd(){

userService.add(new User("zs",23));

}

}

运行后,项目报错,但是数据并没有插入到数据库,把int i = 1 /0;去掉后,插入成功;

注意:@Transactional也可以加载类上(不推荐);可以通过readOnly属性,设置是否使只读,默认false,开启事务;可以通过propagation设置事务的传播级别,默认REQUIRED;

事物是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。 如果使用了try捕获异常时,一定要在catch里面手动回滚。

事物手动回滚代码TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

如下:

@Transactional

public void add(User user) {

try{

userDao.addUser(user.getName(),user.getAge());

int i = 1/0;//故意制造一个错误,看一下事务是否生效了

}catch (Exception e){

//如果必须try-catch,一定要手动回滚

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

e.printStackTrace();

}

}

}

三、Spring中的事务传播行为

1、Propagation.REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。默认的。

2、Propagation.SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。(如果当前有事物,就用当前事物,如果当前没有事物,就以非事物进行执行)

3、Propagation.MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。

4、Propagation.REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。

5、Propagation.NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

6、Propagation.NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

7、Propagation.NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

大家可以自己自己测试以下:

@Service

public class UserServiceImpl implements UserService {

@Autowired

private UserDao userDao;

@Autowired

private LogService logService;

/**

* 验证事务传播行为

*/

@Transactional(propagation = Propagation.REQUIRED)

public void add(User user) {

userDao.addUser(user.getName(), user.getAge());

logService.addLog("添加了用户"+ user.getName());

throw new RuntimeException("制造错误");

}

}

@Service

public class LogServiceImpl implements LogService {

@Autowired

private LogDao logDao;

@Transactional(propagation = Propagation.REQUIRED)

public void addLog(String context) {

logDao.addLog(context);

}

}

源码:https://gitee.com/itcaofanqi/CaoFanqiStudyRepository/tree/master/stuspring

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL事务传播机制是用来决定事务在不同的操作中如何传播和影响的规则MySQL支持以下几种事务传播机制: 1. 作为默认的传播机制MySQL使用的是REPEATABLE READ(可重复读)级别。在该级别下,事务开始时会创建一个快照,事务中的查询都会使用该快照作为读取数据的基础。这意味着在事务中,无论其他事务是否对数据进行了修改,读取的数据都是一致的。 2. READ COMMITTED(已提交读)是另一种常用的传播机制。在该级别下,事务中的查询会读取到其他已提交事务所做的修改,而不是使用快照。这意味着同一事务内的两个查询可能会返回不一致的结果。 3. READ UNCOMMITTED(未提交读)是最低级别的传播机制。在该级别下,事务中的查询会读取到其他未提交事务所做的修改。这可能导致脏读(读取到未提交的数据)和不可重复读(同一查询返回不同结果)。 4. SERIALIZABLE(可串行化)是最高级别的传播机制。在该级别下,事务串行执行,确保每个事务都感知到其他事务所做的修改。这种级别保证了最高的数据一致性,但也会带来性能损耗。 要设置事务传播机制,可以使用以下语句: ``` SET TRANSACTION ISOLATION LEVEL <level>; ``` 其中,<level>可以是上述提到的几种传播机制之一。 需要注意的是,不同的数据库管理系统可能对事务传播机制有所不同,以上是MySQL传播机制示例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值