【spring系列】之13:spring声明式事务环境搭建

本章分两节

  • 1.事务环境搭建
  • 2.事务原理分析

 

事务环境搭建

  • 1.导入相关依赖(数据源、数据库驱动、Spring-jdbc模块)
  • 2.配置数据源、mybatis的Mapper
  • 3.给方法上标注 @Transactional 表示当前方法是一个事务方法;
  • 4.@EnableTransactionManagement 开启基于注解的事务管理功能
  • 5.配置事务管理器来控制事务;

 

1.导入相关依赖(数据源、数据库驱动、Spring-jdbc模块)

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
		</dependency>

2.配置数据源、mybatis的Mapper

@Configuration
@MapperScan("com.ddc.mcn.mapper")
@Data
public class MybatisConf {

	@Value("${apollo.dataSource.read01.jdbc.url}")
	private String read01url;

	@Value("${apollo.dataSource.read01.jdbc.username}")
	private String read01username;

	@Value("${apollo.dataSource.read01.jdbc.password}")
	private String read01password;

	@Value("${apollo.dataSource.write01.jdbc.url}")
	private String write01url;

	@Value("${apollo.dataSource.write01.jdbc.username}")
	private String write01username;

	@Value("${apollo.dataSource.write01.jdbc.password}")
	private String write01password;

	// @Bean
	private DruidDataSource read01DataSource() {
		DruidDataSource read01DataSource = new DruidDataSource();
		read01DataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		read01DataSource.setUrl(read01url);
		read01DataSource.setUsername(read01username);
		read01DataSource.setPassword(read01password);
		read01DataSource.setInitialSize(5);
		read01DataSource.setMaxActive(50);
		read01DataSource.setMinIdle(5);
		// 配置获取连接等待超时的时间
		read01DataSource.setMaxWait(60000);
		read01DataSource.setPoolPreparedStatements(false);
		read01DataSource.setMaxPoolPreparedStatementPerConnectionSize(0);
		read01DataSource.setValidationQuery("SELECT 'x'");
		read01DataSource.setValidationQueryTimeout(5);
		read01DataSource.setTestOnBorrow(false);
		read01DataSource.setTestOnReturn(false);
		read01DataSource.setTestWhileIdle(true);
		// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
		read01DataSource.setTimeBetweenEvictionRunsMillis(60000);
		// 配置一个连接在池中最小生存的时间,单位是毫秒
		read01DataSource.setMinEvictableIdleTimeMillis(300000);
		read01DataSource.setMaxEvictableIdleTimeMillis(1800000);
		read01DataSource.setRemoveAbandoned(true);
		try {
			read01DataSource.setFilters("stat");
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return read01DataSource;
	}

	// @Bean
	private DruidDataSource write01DataSource() {
		DruidDataSource write01DataSource = new DruidDataSource();
		write01DataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
		write01DataSource.setUrl(write01url);
		write01DataSource.setUsername(write01username);
		write01DataSource.setPassword(write01password);
		write01DataSource.setInitialSize(5);
		write01DataSource.setMaxActive(50);
		write01DataSource.setMinIdle(5);
		// 配置获取连接等待超时的时间
		write01DataSource.setMaxWait(60000);
		write01DataSource.setPoolPreparedStatements(false);
		write01DataSource.setMaxPoolPreparedStatementPerConnectionSize(0);
		write01DataSource.setValidationQuery("SELECT 'x'");
		write01DataSource.setValidationQueryTimeout(5);
		write01DataSource.setTestOnBorrow(false);
		write01DataSource.setTestOnReturn(false);
		write01DataSource.setTestWhileIdle(true);
		// 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
		write01DataSource.setTimeBetweenEvictionRunsMillis(60000);
		// 配置一个连接在池中最小生存的时间,单位是毫秒
		write01DataSource.setMinEvictableIdleTimeMillis(300000);
		write01DataSource.setMaxEvictableIdleTimeMillis(1800000);
		write01DataSource.setRemoveAbandoned(true);
		try {
			write01DataSource.setFilters("stat");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return write01DataSource;
	}

	@Bean
	@Primary
	public DynamicDataSource dynamicDataSource() {
		Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
		targetDataSources.put("write01", write01DataSource());
		targetDataSources.put("read01", read01DataSource());
		DynamicDataSource dataSource = new DynamicDataSource();
		dataSource.setTargetDataSources(targetDataSources);
		dataSource.setDefaultTargetDataSource(write01DataSource());
		return dataSource;
	}

	@Bean
	public SqlSessionFactoryBean sqlSessionFactoryBean() throws IOException {
		SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(dynamicDataSource());
		sqlSessionFactoryBean.setTypeAliasesPackage("com.ddc.mcn.domain");
		PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
		sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:mybatis/*Mapper.xml"));
		sqlSessionFactoryBean.setConfigLocation(resolver.getResource("classpath:config/mybatis-config.xml"));
		return sqlSessionFactoryBean;
	}

}

因为我用的是读写分离的,所有有两个数据源,关于如何在service层做数据库的读写分离,后面会单独写文章介绍

给方法上标注 @Transactional 表示当前方法是一个事务方法;

	@Transactional
	@Override
	@DataSource(DataSourceTypeEnum.MASTER)
	public int save(UserRequestDTO user) {

		UserDO u = new UserDO();
		BeanUtils.copyProperties(user, u);
		u.setGmtCreate(new Date());
		int count = userMapper.save(u);
		Long userId = u.getUserId();
		List<Long> roles = user.getRoleIds();
		userRoleMapper.removeByUserId(userId);
		List<UserRoleDO> list = new ArrayList<>();
		if (roles != null && roles.size() != 0) {
			for (Long roleId : roles) {
				UserRoleDO ur = new UserRoleDO();
				ur.setUserId(userId);
				ur.setRoleId(roleId);
				list.add(ur);
			}
		}

		if (list.size() > 0) {
			userRoleMapper.batchSave(list);
		}
		return count;
	}

4.@EnableTransactionManagement 开启基于注解的事务管理功能

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
public class TransactionManagementConf implements TransactionManagementConfigurer {

	// @Resource(name = "txManager")
	private PlatformTransactionManager transactionManager;

	// 创建事务管理器1,其中 dataSource 框架会自动为我们注入
        //这一步为操作步骤5.配置事务管理器来控制事务;
	@Bean
	@Qualifier(value = "transactionManager")
	public PlatformTransactionManager txManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}

	public PlatformTransactionManager annotationDrivenTransactionManager() {
		return transactionManager;
	}

}

其中,以下代码为配置事务管理器

    //这一步为操作步骤5.配置事务管理器来控制事务;
	@Bean
	@Qualifier(value = "transactionManager")
	public PlatformTransactionManager txManager(DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}

 

以上步骤完成,便实现了声明式事务的全部编写步骤,其中在第四步,TransactionManagementConf实现了TransactionManagementConfigurer接口,这个主要的作用是,返回系统默认的事务管理器,因为我们一个系统当中,可能会出现多种事务类型,比如JpaTransactionManager,DataSourceTransactionManager,HibernateTransactionManager等

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值