1. 足够简单
说实话要实现事务管理,给一个方法添加一个注解,则该方法自动实现事务,足够简单了,我也没法想还有更简单的么。
这个注解就是@Transactional,就是这么优秀。所谓的声明式事务管理,就是通过在方法(或类)上添加注解声明来启用事务的方式。
2. 声明式事务实例
第一,正常的编写数据对象Do与数据库表blog对应:
package org.maoge.transactionaldemo; /** * @theme 数据对象--博客 * @author maoge * @date 2020-01-27 */ public class BlogDo { private Long id; private String title; private String author; private String content; // 省略get get }
第二,编写数据库操作类,通过NamedParameterJdbcTemplate 操作数据库。
package org.maoge.transactionaldemo; import java.util.HashMap; import java.util.Map; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.transaction.annotation.Transactional; /** * @theme DAO--博客 * @author maoge * @date 2020-01-29 */ public class BlogDao { public NamedParameterJdbcTemplate getNamedTemplate() { return namedTemplate; } public void setNamedTemplate(NamedParameterJdbcTemplate namedTemplate) { this.namedTemplate = namedTemplate; } private NamedParameterJdbcTemplate namedTemplate; /** * 新增 */ public void insert(BlogDo blog) { Map<String, Object> map = new HashMap<>(); map.put("author", blog.getAuthor()); map.put("content", blog.getContent()); map.put("title", blog.getTitle()); // 注意使用:xxx占位 namedTemplate.update("insert into blog(author,content,title)values(:author,:content,:title)", map); } }
第三,编写BlogService,调用BlogDao类型对象操作数据库。此处注意我们在方法addTwoBlog上添加了注解@Transactional
,这样就开启了事务。
package org.maoge.transactionaldemo; import org.springframework.transaction.annotation.Transactional; public class BlogService { public BlogDao getBlogDao() { return blogDao; } public void setBlogDao(BlogDao blogDao) { this.blogDao = blogDao; } private BlogDao blogDao; @Transactional public void addTwoBlog() { BlogDo blog = new BlogDo(); blog.setContent("测试"); blogDao.insert(blog); int a = 1 / 0;// 发生异常,导致事务回滚,所以并不会插入任何一行数据 blogDao.insert(blog); } }
第四,通过配置类激活声明式事务,并且将个类注册为组件,这里跟之前的区别就是添加了@EnableTransactionManagement // 激活基于注解的声明式事务
。
package org.maoge.transactionaldemo; import javax.sql.DataSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import org.springframework.transaction.support.TransactionTemplate; import com.alibaba.druid.pool.DruidDataSource; @Configuration // 表明该类是Spring配置类,需要扫描该类的配置信息 @EnableTransactionManagement // 激活基于注解的声明式事务 public class SpringConfig { /** * 定义数据源bean */ @Bean public DataSource dataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/myblog?useUnicode=true&characterEncoding=utf-8"); dataSource.setUsername("root"); dataSource.setPassword("Easy@0122"); return dataSource; } /** * 定义事务管理bean */ @Bean public PlatformTransactionManager transactionManager() { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource());// 注入dataSource return transactionManager; } /** * 定义TransactionTemplate类型的bean */ @Bean public TransactionTemplate transactionTemplate() { TransactionTemplate transactionTemplate = new TransactionTemplate(); transactionTemplate.setTransactionManager(transactionManager());// 注入事务管理器 return transactionTemplate; } /** * 配置namedParameterJdbcTemplate组件 */ @Bean public NamedParameterJdbcTemplate namedParameterJdbcTemplate() { NamedParameterJdbcTemplate template = new NamedParameterJdbcTemplate(dataSource());// 注入dataSource return template; } /** * 为BlogDao注册bean */ @Bean public BlogDao blogDao() { BlogDao blogDao = new BlogDao(); blogDao.setNamedTemplate(namedParameterJdbcTemplate());// 注入namedParameterJdbcTemplate return blogDao; } /** * 为BlogService注册bean */ @Bean public BlogService blogService() { BlogService blogService = new BlogService(); blogService.setBlogDao(blogDao());// 注入blogDao return blogService; } }
第五,测试
package org.maoge.transactionaldemo; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class Main { public static void main(String[] args) { // 获取容器 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); // 容器中获取数据库操作组件 BlogService blogService = (BlogService) context.getBean("blogService"); blogService.addTwoBlog(); } }
当执行addTwoBlog中的int a = 1 / 0;时,发生异常,导致事务回滚,所以并不会插入任何一行数据。
3. 总结
声明式注解太简单了,首先通过@EnableTransactionManagement激活注解,然后需要开启事务的方法上添加@Transactional即可。
本篇组件采用了JavaConfig的配置方式,实际上对于BlogDao、BlogService可以通过在类上添加注解@Repository、@Service或@Component的方式将其注册为bean,效果是一样的。