一、配置数据库连接,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 ,我们会觉得麻烦,所以此方式并不常用。