Spring-----事务
一、spring的声明式事务
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--加载外部属性文件 例: 加载properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:component-scan base-package="com.oracle.service"></context:component-scan>
<!--整合mybatis-->
<bean id="userService" class="com.oracle.service.impl.UserServiceImpl">
<!--注意 在注入的时候一定要有set方法-->
<!--此处ref注入的对象都已经被sqlSessionFactory扫描时全部创建 默认id就是类名首字母小写-->
<property name="userMapper" ref="userMapper"></property>
</bean>
<bean id="accountService" class="com.oracle.service.impl.AccountServiceImpl">
<property name="accountMapper" ref="accountMapper"></property>
</bean>
<!--由spring创建sqlSessionFactory 对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入连接池对象-->
<property name="dataSource" ref="druidDataSource"></property>
<!--创建sqlSessionFactory需要加载配置文件-->
<!--<property name="configLocation" value="mybatis.xml"></property>-->
<!--给实体类配置别名 默认为类名首字母小写-->
<property name="typeAliasesPackage" value="com.oracle.beans"></property>
<!--映射文件与dao目录结构不一致时配置映射文件的路径-->
<!--<property name="mapperLocations" value="classpath:xxxx/*.xml"></property>-->
<property name="plugins">
<array>
<!--同样也可以配置多个插件-->
</array>
</property>
</bean>
<!--指定创建那些mapper对象 ioc容器一加载,立马创建扫描的所有mapper对象-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--在配置sqlSessionFactory的时候可以配置多个 所以下面这条配置就是在多个的情况下指定一个来扫描dao类-->
<!--此条配置由哪一个sqlSessionFactory来扫描 并创建mapper对象 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!--指定一个dao类的存放路径 在扫描时需要根据此路径-->
<property name="basePackage" value="com.oracle.dao"></property>
</bean>
<!--druid连接池 配置 注意:在mybatis中就不要再配置environments了-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--<bean id="transactionManager" class="com.oracle.beans.TransactionManager"></bean>-->
<!--设置切面 将模拟spring事务增强到业务中-->
<!--<aop:config>
<aop:aspect ref="transactionManager">
<aop:pointcut id="pt01" expression="execution(* com.oracle.service..*.*(..))"/>
<aop:before method="star" pointcut-ref="pt01"></aop:before>
<aop:after-returning method="end" pointcut-ref="pt01"></aop:after-returning>
<aop:after method="close" pointcut-ref="pt01"></aop:after>
<aop:after-throwing method="rollback" pointcut-ref="pt01"></aop:after-throwing>
</aop:aspect>
</aop:config>-->
<!--事务管理器 该类中已经封装好了提交事务、开始事务、回滚事务、关闭资源-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--使用aop自带的事务管理需要对事务管理器进行封装-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--设置事务控制的属性-->
<tx:attributes>
<!--isolation设置隔离级别 作用于具体的方法 也可以使用*来通配所有方法-->
<!--propagation设置事务的传播 还可以使用timeout设置事务的超时时间-->
<tx:method name="*" isolation="DEFAULT" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<!--aop传统切面-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.oracle.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
</beans>
注解配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--加载外部属性文件 例: 加载properties文件-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<context:component-scan base-package="com.oracle.service"></context:component-scan>
<!--由spring创建sqlSessionFactory 对象-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入连接池对象-->
<property name="dataSource" ref="druidDataSource"></property>
<!--创建sqlSessionFactory需要加载配置文件-->
<!--<property name="configLocation" value="mybatis.xml"></property>-->
<!--给实体类配置别名 默认为类名首字母小写-->
<property name="typeAliasesPackage" value="com.oracle.beans"></property>
<!--映射文件与dao目录结构不一致时配置映射文件的路径-->
<!--<property name="mapperLocations" value="classpath:xxxx/*.xml"></property>-->
<property name="plugins">
<array>
<!--同样也可以配置多个插件-->
</array>
</property>
</bean>
<!--指定创建那些mapper对象 ioc容器一加载,立马创建扫描的所有mapper对象-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--在配置sqlSessionFactory的时候可以配置多个 所以下面这条配置就是在多个的情况下指定一个来扫描dao类-->
<!--此条配置由哪一个sqlSessionFactory来扫描 并创建mapper对象 -->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
<!--指定一个dao类的存放路径 在扫描时需要根据此路径-->
<property name="basePackage" value="com.oracle.dao"></property>
</bean>
<!--druid连接池 配置 注意:在mybatis中就不要再配置environments了-->
<bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--事务管理器 该类中已经封装好了提交事务、开始事务、回滚事务、关闭资源-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="druidDataSource"></property>
</bean>
<!--开启事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
</beans>
package com.oracle.service.impl;
import com.oracle.dao.AccountMapper;
import com.oracle.service.AccountService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Data
@Service("accountService")
@Transactional(isolation = Isolation.DEFAULT,propagation = Propagation.SUPPORTS)
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
/**
*
* @param outId 收款人
* @param inId 转账人
* @param money 金额
*/
@Override
@Transactional(isolation = Isolation.DEFAULT)//同样可以在方法上直接配置 会覆盖类上的事务配置
public void transfer(Integer outId, Integer inId, double money) {
accountMapper.outMoney(outId,money);
accountMapper.addMoney(inId,money);
}
}
java类配置
package com.oracle.config;
import com.alibaba.druid.pool.DruidDataSource;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
@Configuration
@PropertySource("classpath:jdbc.properties")
@ComponentScan(basePackages = "com.oracle.service")
@MapperScan(basePackages = "com.oracle.dao")
@EnableTransactionManagement //开启事务注解驱动
public class SpringConfig {
@Value("${jdbc.driver}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean //指定一个连接池,通过方法名 在同类型连接池有多个的情况下
public SqlSessionFactoryBean sqlSessionFactoryBean(@Qualifier("dataSource") DataSource dataSource){
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
return sqlSessionFactoryBean;
}
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public DataSourceTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}