一些关于事务和Alibaba Druid的相关问题

事务的本质

  • Spring 的声明式事务本质上是通过 AOP 来增强了类的功能
  • Spring 的 AOP 本质上就是为类做了一个代理
    看似在调用自己写的类,实际用的是增强后的代理类

我们在之前写个一个程序。是关于事务的,当时在invokeInsertThenRollback()方法中,没有事务回滚,现在我们修改一下这个方法,让它有事务回滚。

@Component
public class FooServiceImpl implements FooService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private FooServiceImpl fooService;

    @Override
    @Transactional
    public void insertRecord() {
        jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('AAA')");
    }

    @Override
    @Transactional(rollbackFor = RollbackException.class)
    public void insertThenRollback() throws RollbackException {
        jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
        throw new RollbackException();
    }

    @Override
    public void invokeInsertThenRollback() throws RollbackException {
        fooService.insertThenRollback();
    }
}

结果如下:
在这里插入图片描述
我们可以看到,BBB回滚了。用这种方式,让我们一个不带事务的方法,调用带事务的方法。

REQUIRES_NEW 与 NESTED 事务传播特性的说明

REQUIRES_NEW,始终启动一个新事务

  • 两个事务没有关联

NESTED,在原事务内启动一个内嵌事务

  • 两个事务有关联
  • 外部事务回滚,内嵌事务也会回滚

我们以一个例子为例:

public class FooServiceImpl implements FooService {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    @Autowired
    private FooService fooService;

    @Override
    @Transactional(rollbackFor = RollbackException.class, propagation = Propagation.REQUIRES_NEW)
    public void insertThenRollback() throws RollbackException {
        jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('BBB')");
      //  throw new RollbackException();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void invokeInsertThenRollback() {
        jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('AAA')");
        try {
            fooService.insertThenRollback();
        } catch (RollbackException e) {
            log.error("RollbackException", e);
        }
        throw new RuntimeException();
    }
}

REQUIRES_NEW情况下
在这里插入图片描述两个事务互相不影响

NESTED情况下
在这里插入图片描述
外部事务回滚,内嵌事务也会回滚

Alibaba Druid 的一些展开说明

慢 SQL 日志
系统属性配置

  • druid.stat.logSlowSql=true
  • druid.stat.slowSqlMillis=3000
    在Java启动的时候,输入这两个命令

Spring Boot

  • spring.datasource.druid.filter.stat.enabled=true
    通过springbootstart,就是的Druid的springboot-start会默认开启统计的filter

  • spring.datasource.druid.filter.stat.log-slow-sql=true
    开启慢SQL查询

  • spring.datasource.druid.filter.stat.slow-sql-millis=3000
    超过3000ms的sol语句会被我们抓出来

以一个例子为例:

@SpringBootApplication
@Slf4j
@EnableTransactionManagement(proxyTargetClass = true)
public class DruidDemoApplication implements CommandLineRunner {
	@Autowired
	private DataSource dataSource;
	@Autowired
	private FooService fooService;

	public static void main(String[] args) {
		SpringApplication.run(DruidDemoApplication.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		log.info(dataSource.toString());
		new Thread(() -> fooService.selectForUpdate()).start();
		new Thread(() -> fooService.selectForUpdate()).start();
	}
}

@Repository
public class FooService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void selectForUpdate() {
        jdbcTemplate.queryForObject("select id from foo where id = 1 for update", Long.class);
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
        }
    }
}

结果如下:
在这里插入图片描述
我们可以看到,这条慢SQL被查出来。
此外,我们还可以看到,连接池的状态和两个连接的详细信息。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值