一天一个小知识,JdbcTemplate是用来干啥的呢?相信JDBC都学过,JDBC中释放连接和其他资源都是通过try()来实现的,而JdbcTemplateAPI就是来拯救这些繁琐的操作。声明式事务管理也是为了简化每个业务处理类中的事务管理,保证数据的原子性。
JdbcTemplate
1)定义Bean
需要传入DataSource,具体代码如下
@Bean
JdbcTemplate createJdbcTemplate(@Autowired DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
之后只要在具体的代码中注入使用就行了
2)具体的使用方法
最基础的用法就是T execute(String sql, PreparedStatementCallback action)示例代码如下:
public User getUserByName(String name) {
// 需要传入SQL语句,以及PreparedStatementCallback:
return jdbcTemplate.execute("SELECT * FROM users WHERE name = ?", (PreparedStatement ps) -> {
// PreparedStatement实例已经由JdbcTemplate创建,并在回调后自动释放:
ps.setObject(1, name);
try (var rs = ps.executeQuery()) {
if (rs.next()) {
return new User( // new User object:
rs.getLong("id"), // id
rs.getString("email"), // email
rs.getString("password"), // password
rs.getString("name")); // name
}
throw new RuntimeException("user not found by id.");
}
});
}
里面最好用的还是定义和查询字段一样的JavaBean可以根据查询结果直接映射到Bean中返回:
public List<User> getUser(String name) {
return jdbcTemplate.query("select * from user where name = ?", new Object[] {name}, new BeanPropertyRowMapper<>(User.class));
}
声明式事务管理
1)定义事务管理类
Spring提供了一个叫PlatformTransactionManager的东西,我们需要定义这么一个类并且开启允许声明式的事务管理@EnableTransactionManager,这个声明式的事务管理原理也是代理模式,所以可以把AOP切面的的允许注解给删除。
2)Transaction注解的使用
我们在需要开启事务的方法上加上注解@Transaction,后面可以加当抛出异常时回滚,默认是RuntimeException回滚也可以自定义异常回滚,如果不想加这个注释的话我们定义的业务异常最好是RuntimeException的子类。
3)事务边界,以及事务传播
前面两个点只是简单的使用方法,其实真正重要的是理解事务的边界以及事务的传播性,一般事务的边界就是定义注解的方法开始和结束,而当一个方法中加入了另一个方法也含有事务是,这是就变得复杂了许多。
默认的事务传播级别是REQUIRED,表示新的事务如果当前又事务就不开启新事务直接加入当前事务,它满足绝大部分的需求。还有一些其他的传播级别:
SUPPORTS:表示如果有事务,就加入到当前事务,如果没有,那也不开启事务执行。这种传播级别可用于查询方法,因为SELECT语句既可以在事务内执行,也可以不需要事务;
MANDATORY:表示必须要存在当前事务并加入执行,否则将抛出异常。这种传播级别可用于核心更新逻辑,比如用户余额变更,它总是被其他事务方法调用,不能直接由非事务方法调用;
REQUIRES_NEW:表示不管当前有没有事务,都必须开启一个新的事务执行。如果当前已经有事务,那么当前事务会挂起,等新事务完成后,再恢复执行;
NOT_SUPPORTED:表示不支持事务,如果当前有事务,那么当前事务会挂起,等这个方法执行完成后,再恢复执行;
NEVER:和NOT_SUPPORTED相比,它不但不支持事务,而且在监测到当前有事务时,会抛出异常拒绝执行;
NESTED:表示如果当前有事务,则开启一个嵌套级别事务,如果当前没有事务,则开启一个新事务。