足够简单
说实话要实现事务管理,给一个方法添加一个注解,则该方法自动实现事务,足够简单了,我也没法想还有更简单的么。
这个注解就是@Transactional,就是这么优秀。所谓的声明式事务管理,就是通过在方法(或类)上添加注解声明来启用事务的方式。
声明式事务实例
第一,正常的编写数据对象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;
时,发生异常,导致事务回滚,所以并不会插入任何一行数据。
总结
声明式注解太简单了,首先通过@EnableTransactionManagement
激活注解,然后需要开启事务的方法上添加@Transactional
即可。
本篇组件采用了JavaConfig的配置方式,实际上对于BlogDao、BlogService可以通过在类上添加注解@Repository
、@Service
或@Component
的方式将其注册为bean,效果是一样的。