Spring之路(40)–使用@Transactional进行声明式事务管理如此简单

足够简单

说实话要实现事务管理,给一个方法添加一个注解,则该方法自动实现事务,足够简单了,我也没法想还有更简单的么。

这个注解就是@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,效果是一样的。

Spring之路(40)–使用@Transactional进行声明式事务管理如此简单Spring之路(40)–使用@Transactional进行声明式事务管理如此简单 熊猫大哥大 博客专家 发布了359 篇原创文章 · 获赞 241 · 访问量 53万+ 他的留言板 关注
上一篇:hibernate 掉过的坑小结(一)


下一篇:学习Spring-Data-Jpa(二十二)---事务处理