SpringAOP+ Mybatis + duird实现事务管理(使用xml配置事务)

一、配置数据库连接,mapper扫描以及事务控制

       <context:property-placeholder order="1" location="classpath:jdbc.properties" ignore-unresolvable="true"/>

	<!-- DataSource数据源,使用druid连接池 -->
	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
		<property name="url" value="${jdbc.url}"></property>
		<property name="username" value="${jdbc.username}"></property>
		<property name="password" value="${jdbc.password}"></property>
		<!-- 指定连接数据库连接池的最小连接数 -->
		<property name="minIdle" value="${jdbc.minIdle}"></property>
		<!-- 指定连接数据库连接池的最大连接数 -->
		<property name="maxActive" value="${jdbc.maxActive}"></property>
		<!--初始化接数据库连接池 -->
		<property name="initialSize" value="${jdbc.initialSize}"></property>
		<!-- 指定连接数据库连接池的连接的最大空闲时间 -->
		<property name="maxWait" value="${jdbc.maxWait}"></property>
		<!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒。 -->
		<property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"></property>
		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
		<property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" />
		<!-- 用来检测连接是否有效的sql,要求是一个查询语句 -->
		<property name="validationQuery" value="${jdbc.validationQuery}"></property>
		<property name="testWhileIdle" value="${jdbc.testWhileIdle}"></property>
		<property name="testOnBorrow" value="${jdbc.testOnBorrow}" />
		<property name="testOnReturn" value="${jdbc.testOnReturn}" />
		<!-- 配置监控统计拦截的filters,去掉后监控界面sql无法统计 -->
		<property name="filters" value="${jdbc.filters}" />
		<!-- 长时间不适用的连接强制关闭 -->
		<property name="removeAbandoned" value="${jdbc.removeAbandoned}" />
		<!-- 超过30分钟开始关闭空闲连接 -->
		<property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}" />
		<property name="maxPoolPreparedStatementPerConnectionSize" value="${jdbc.maxPoolPreparedStatementPerConnectionSize}"/>
	</bean>
	
	<!-- SqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="mapperLocations" value="classpath*:com/test/dao/userMysqlDao.xml" />
		
	</bean>
	<!-- scan for mappers and let them be autowired -->
	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.test.dao" />
	</bean>
	
	<tx:annotation-driven transaction-manager="transactionManager"/>
	
	<!--事务管理DataSourceTransactionManager -->
	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource" />
		<property name="globalRollbackOnParticipationFailure" value="false" />
	</bean>

	<tx:advice id="txAdvice" transaction-manager="transactionManager">
		<tx:attributes>
			<tx:method name="select*" read-only="true" propagation="SUPPORTS" />
			<tx:method name="find*" read-only="true" propagation="SUPPORTS" />
			<tx:method name="get*" read-only="true" propagation="SUPPORTS" />
			<tx:method name="query*" read-only="true" propagation="SUPPORTS" />
			<tx:method name="index*" propagation="SUPPORTS" />
			<tx:method name="save*" propagation="REQUIRED"  rollback-for="Exception" />
			<tx:method name="update*" propagation="REQUIRED"/>
			<tx:method name="add*" propagation="REQUIRED"/>
			<tx:method name="edit*" propagation="REQUIRED"/>
			<tx:method name="eaa*" propagation="REQUIRED"/>
			<tx:method name="delete*" propagation="REQUIRED"/>
			<tx:method name="start*" propagation="REQUIRED"/>
			<tx:method name="*" propagation="REQUIRED"/>
		</tx:attributes>
	</tx:advice>
	
	<aop:config>
		<aop:pointcut id="baseServiceMethods" expression="execution(public * com.test..service..*.*(..))" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="baseServiceMethods" />
	</aop:config> 

jdbc.properties配置:

jdbc.url=
jdbc.username=
jdbc.password=

#指定连接数据库连接池的最小连接数
jdbc.minIdle=10
#指定连接数据库连接池的最大连接数
jdbc.maxActive=30
#初始化接数据库连接池
jdbc.initialSize=0
#指定连接数据库连接池的连接的最大空闲时间单位毫秒
jdbc.maxWait=12000
#配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒。
jdbc.timeBetweenEvictionRunsMillis=60000
#配置一个连接在池中最小生存的时间,单位是毫秒
jdbc.minEvictableIdleTimeMillis=300000
#用来检测连接是否有效的sql,要求是一个查询语句
jdbc.validationQuery=SELECT 1 FROM dual
jdbc.testWhileIdle=true
jdbc.testOnBorrow=true
jdbc.testOnReturn=false
#配置监控统计拦截的filters,去掉后监控界面sql无法统计
jdbc.filters=stat
#长时间不适用的连接强制关闭
jdbc.removeAbandoned=true
#超过30分钟开始关闭空闲连接
jdbc.removeAbandonedTimeout=1800
jdbc.maxPoolPreparedStatementPerConnectionSize=30

二、编写service方法测试:

@Service
public class UserServiceImpl implements UserService {

    @Resource
    UserDao userDao;

    @Override
    public void test() {
	int count = userDao.deleteById(1056L);
	System.out.println(">>>>>>>>>>>>>>>"+count);
	UserDo user = new UserDo();
	user.setId(88888);
	userDao.save(user);
    }

}
import com.test.domain.UserDo;

public interface UserDao {
    
    int save(@Param("model") UserDo user);
    
    int deleteById(Long id);

}

控制台输出:




       执行删除的 时候没有报错,执行新增的时候报错了。但是数据库中删除的数据还是存在的,说明事务回滚了。至此配置事务成功。代码并没有写全,但重要代码都在上面,请读者自行补全进行测试。

三、配置事务标签简介:

1、tx:advice    id是该advice bean的标识,而transaction-manager则必须引用一个PlatformTransactionManager bean。 

2、tx:method属性:
name:方法名的匹配模式,通知根据该模式寻找匹配的方法。 
propagation:设定事务定义所用的传播级别。 
isolation:设置事务的隔离级别。 
timeout:指定事务的超时(秒)。 
read-only:该属性为true指示事务是只读的 
no-rollback-for:以逗号分隔的异常类的列表,目标方法可以跑出这些异常而不会导致通知执行回滚 

rollback-for:以逗号分隔的异常类的列表,当目标方法跑出这些异常时会导致通知执行回滚。默认情况下,该列表为空,因此不在no-rollback-for列表中的任何运行时异常都会导致回滚。 

3、<tx:method>中isolation(隔离)和propagation(传播)参数的含义: 
getIsolationLevel:他对其他事务所看到的数据变化进行控制。 
事务隔离级别: 
隔离级别 说明 
ISOLATION_DEFAULT 默认级别(对大多数数据库来说就是ISOLATION_READ_COMMITTED) 
ISOLATION_READ_UNCOMMITTED 最低的隔离级别。事实上我们不应该隔离级别,因为在事务完成前,其他事务可以看到该事务所修改的数据。而在其他事务提交前,该事务也可以看到其他事务所做的修改。 
ISOLATION_READ_COMMITTED 大多数数据库的默认级别。在事务完成前,其他事务无法看到该事务所修改的数据。遗憾的是,在该事务提交后,你就可以查看其他事务插入活更新的数据。这意味着在事务的不同点上,如果其他事务修改数据,你会看到不同的数据。 
ISOLATION_REPEATABLE_READ 该隔离级别确保如果在事务中查询了某个数据集,你至少还能再次查询到相同的数据集,即使其他事务修改了所查询的数据。然而如果其他事务插入了新数据,你就可以查询到该新插入的数据。 
ISOLATION_SERIALIZABLE 代价最大、可靠性最高的隔离级别,所有的事务都是俺顺序一个接一个的执行。 

getPropagationBehavior:指定了当代码请求一个新的事务时Spring所做的事情。 
传播行为指: 
传播行为 说明 
PROPAGATION_REQUIRED 当前如果有事务,Spring就会使用该事务;否则会开始一个新事务。 
PROPAGATION_SUPPORTS 当前如果有事务,Spring就会使用该事务;否则不会开启一个新事务。 
PROPAGATION_MANDATORY 当前如果有事务,Spring就会使用该事务;否则会抛出异常。 
PROPAGATION_REQUIRES_NEW Spring总会开始一个新事务。如果当前有事务,则该事务挂起。 
PROPAGATION_NOT_SUPPORTED Spring不会执行事务中的代码。代码总是在非事务环境下执行,如果当期有事务,则该事务挂起。 
PROPAGATION_NEVER 即使当前有事务,Spring也会在飞事务环境下执行。如果当前有事务,则抛出异常。 
PROPAGATION_NESTED 如果当前有事务,则在嵌套事务中执行。如果没有,那么执行情况与PROPAGATION_REQUIRED一样。 

四、另一种事务配置方式

除了本文介绍的事务配置以外,简单介绍一下另外一种基于注解配置事务

1、    Spring.xml 中配置事务注解驱动。

        <tx:annotation-driven transaction-manager="transactionManager"/> 

        <aop:aspectj-autoproxy /> 

2、   需控制事务的方法上加注解@Transactional 

你可以指定传播、隔离级别、超时以及允许和不允许的异常。 
 @Transactional注解的属性: 
propagation:指定事务定义中使用的传播 
isolation:设定事务的隔离级别 
timeout:指定事务的超市(秒) 
readOnly:指定事务的超时 
noRollbackFor:目标方法可抛出的异常所构成的数组,但通知仍会提交事务 

rollbackFor:异常所构成的数组,如果目标方法抛出了这些异常,通知就会回滚事务 

如果每个方法上都需要写注解@Transactional ,我们会觉得麻烦,所以此方式并不常用。

猜你喜欢

转载自blog.csdn.net/weixin_42184707/article/details/80351076