Spring之Spring的事务控制

生活中,最使人疲惫的往往不是道路的遥远,而是心中的郁闷;最使人痛苦的往往不是生活的不幸,而是希望的破灭;最使人颓废的往往不是前途的坎坷,而是自信的丧失;最使人绝望的往往不是挫折的打击,而是心灵的死亡。所以我们要有自己的梦想,让梦想的星光指引着我们走出落漠,走出惆怅,带着我们走进自己的理想。

导读:本篇文章讲解 Spring之Spring的事务控制,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

一、Spring中的事务

Spring 并不直接管理事务,而是提供了多种事务管理器,将事务管理的职责委托给JDBC、Hibernate等持久化机制所提供的相关平台框架的事务来实现。

Spring框架为提供了一组事务控制的接口,该接口是在spring-tx-*.jar 中。

PlatformTransactionManager

PlatformTransactionManager接口是 spring的事务管理器,提供了操作事务的方法

public interface PlatformTransactionManager extends TransactionManager {
	//获取事务状态信息
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
	//提交事务
    void commit(TransactionStatus var1) throws TransactionException;
	//回滚事务
    void rollback(TransactionStatus var1) throws TransactionException;
}

Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,具体的实现就是各个平台自己的事情。

JDBC 事务管理器

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

Hibernate久化事务管理器

<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

JPA持久化事务管理器

<bean id="transactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

TransactionDefinition

TransactionDefinition接口是事务的信息定义对象

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

	//获取事务传播行为
    default int getPropagationBehavior() {
        return 0;
    }
	//获取事务隔离级别
    default int getIsolationLevel() {
        return -1;
    }
	//获取事务超时时间,默认值是-1,没有超时限制。如果有,以秒为单位进行设置。
    default int getTimeout() {
        return -1;
    }
	//获取事务是否只读,查询时设置为只读。
    default boolean isReadOnly() {
        return false;
    }

	//获取事务对象名称
    @Nullable
    default String getName() {
        return null;
    }

    static TransactionDefinition withDefaults() {
        return StaticTransactionDefinition.INSTANCE;
    }
}

TransactionStatus

TransactionStatus接口是提供事务具体的运行状态信息。

public class DefaultTransactionStatus extends AbstractTransactionStatus {
    @Nullable
    private final Object transaction;
    private final boolean newTransaction;
    private final boolean newSynchronization;
    private final boolean readOnly;
    private final boolean debug;
    @Nullable
    private final Object suspendedResources;

	//事务的默认状态
    public DefaultTransactionStatus(@Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
        this.transaction = transaction;
        this.newTransaction = newTransaction;
        this.newSynchronization = newSynchronization;
        this.readOnly = readOnly;
        this.debug = debug;
        this.suspendedResources = suspendedResources;
    }

	//获取事务
    public Object getTransaction() {
        Assert.state(this.transaction != null, "No transaction active");
        return this.transaction;
    }

	//事务是否存在
    public boolean hasTransaction() {
        return this.transaction != null;
    }

	//获取的事务是否是新的事务
    public boolean isNewTransaction() {
        return this.hasTransaction() && this.newTransaction;
    }
    
    public boolean isNewSynchronization() {
        return this.newSynchronization;
    }

	//是否是只读事务
    public boolean isReadOnly() {
        return this.readOnly;
    }

    public boolean isDebug() {
        return this.debug;
    }

    @Nullable
    public Object getSuspendedResources() {
        return this.suspendedResources;
    }
	
	//获取事务是否回滚
    public boolean isGlobalRollbackOnly() {
        return this.transaction instanceof SmartTransactionObject && ((SmartTransactionObject)this.transaction).isRollbackOnly();
    }

	//获取事务存储点管理对象
    protected SavepointManager getSavepointManager() {
        Object transaction = this.transaction;
        if (!(transaction instanceof SavepointManager)) {
            throw new NestedTransactionNotSupportedException("Transaction object [" + this.transaction + "] does not support savepoints");
        } else {
            return (SavepointManager)transaction;
        }
    }

	//是否是事务存储点管理对象
    public boolean isTransactionSavepointManager() {
        return this.transaction instanceof SavepointManager;
    }

	//刷新事务
    public void flush() {
        if (this.transaction instanceof SmartTransactionObject) {
            ((SmartTransactionObject)this.transaction).flush();
        }

    }
}

事务的隔离级别

MySQL之事务与事务隔离详解

级别 名字 隔离级别 脏读 不可重复读 幻读
1 读未提交 read uncommitted
2 读已提交 read committed
3 可重复读 repeatable read
4 串行化 serializable

事务的传播行为

REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值)

SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务)

MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常

REQUERS_NEW:新建事务,如果当前在事务中,把当前事务挂起。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

NEVER:以非事务方式运行,如果当前存在事务,抛出异常

NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行 REQUIRED 类似的操作。

二、基于 XML 的声明式事务控制

1.添加依赖

   <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
    </dependencies>

2.配置spring.xml

声明式事务控制配置步骤

1、配置事务管理器

2、配置事务的通知         
		导入事务的名称空间和约束 xmlns:tx="http://www.springframework.org/schema/tx"
		
3、配置AOP中的通用切入点表达式
		导入aop的名称空间和约束 xmlns:aop="http://www.springframework.org/schema/aop"
		
4、建立事务通知和切入点表达式的对应关系

5、配置事务的属性
		isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。
        propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。
        read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。
        timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。
        rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。
        no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。	
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 配置accountService-->
    <bean id="accountService" class="cn.ybzy.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!-- 配置accountDao-->
    <bean id="accountDao" class="cn.ybzy.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>


    <!-- 配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/demo"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>

    <!-- 1.配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 2.配置事务通知-->
    <!-- transaction-manager属性表示这个事务通知是哪个事务管理器管理的 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!-- 5.配置事务的属性-->
        <tx:attributes>
            <!-- 一般来说增删改方法 propagation=Required,对于查询方法使用 read-only="true" -->
            <!-- name是必须的,表示与事务属性关联的方法名,对切入点进行细化
            	 通配符(*)可以用来指定一批关联到相同的事务属性的方法,如:'save*'、'update*'等 -->
            	 
            <!--对以add update delete开头的所有方法进行事务处理-->	 
            <tx:method name="add*" propagation="REQUIRED" />
		    <!-- 匹配以 update 开头的所有方法均加入事务 -->
		    <tx:method name="update*" propagation="REQUIRED" />
		    <!-- 匹配以 delete 开头的所有方法均加入事务 -->
		    <tx:method name="delete*" propagation="REQUIRED" />
             <!-- 匹配以 find 开头的所有方法均加入事务,且是只读,不能修改数据库数据 -->
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>

    <!-- 配置aop-->
    <aop:config>
        <!-- 3.配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* cn.ybzy.service.impl.*.*(..))"></aop:pointcut>
        <!--4.建立切入点表达式和事务通知的对应关系 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>
</beans>

3.编写代码

Account实体对象

public class Account implements Serializable {

    private Integer id;
    private String name;
    private BigDecimal money;

	//getter and setter
}

IAccountDao 接口与AccountDaoImpl实现类

public interface IAccountDao {

    /**
     * 根据名称查询账户
     * @param accountName
     * @return
     */
    Account findAccountByName(String accountName);

    /**
     * 更新账户
     * @param account
     */
    void updateAccount(Account account);
}


public class AccountDaoImpl implements IAccountDao {

    
    private JdbcTemplate jdbcTemplate;
    
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    @Override
    public Account findAccountByName(String accountName) {
        List<Account> accounts = jdbcTemplate.query("select * from account where name = ?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        return accounts.get(0);
    }

    @Override
    public void updateAccount(Account account) {
        jdbcTemplate.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
    }
}

IAccountService 接口与AccountServiceImpl实现类

public interface IAccountService {

    /**
     * 转账
     * @param sourceName    转成账户名称
     * @param targetName    转入账户名称
     * @param money         转账金额
     */
    void transfer(String sourceName, String targetName, BigDecimal money);
}


public class AccountServiceImpl implements IAccountService{

    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

    @Override
    public void transfer(String sourceName, String targetName, BigDecimal money) {
             //1根据名称查询转出账户
            Account source = accountDao.findAccountByName(sourceName);
            //2根据名称查询转入账户
            Account target = accountDao.findAccountByName(targetName);
            //3转出账户减钱
            source.setMoney(source.getMoney().subtract(money));
            //4转入账户加钱
            target.setMoney(target.getMoney().add(money));
            //5.更新转出账户
            accountDao.updateAccount(source);

           // int i=1/0;

            //6更新转入账户
            accountDao.updateAccount(target);
    }
}

4.执行测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {

    @Autowired
    private  IAccountService as;

    @Test
    public  void testTransfer(){
        as.transfer("A","B", BigDecimal.valueOf(100));

    }

}

三、基于注解的声明式事务控制

1.添加依赖

   <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
    </dependencies>

2.配置spring.xml

注解的声明式事务控制配置步骤

1、配置事务管理器

2、开启spring对注解事务的支持

3、在需要事务支持的地方使用@Transactional注解
<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 配置扫描的包-->
    <context:component-scan base-package="cn.ybzy"></context:component-scan>

    <!-- 配置JdbcTemplate-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置数据源-->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/demo"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 开启spring对注解事务的支持-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

</beans>

3.编写代码

Account实体对象

public class Account implements Serializable {

    private Integer id;
    private String name;
    private BigDecimal money;

	//getter and setter
}

IAccountDao 接口与AccountDaoImpl实现类

public interface IAccountDao {

    /**
     * 根据名称查询账户
     * @param accountName
     * @return
     */
    Account findAccountByName(String accountName);

    /**
     * 更新账户
     * @param account
     */
    void updateAccount(Account account);
}


@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;
   
    @Override
    public Account findAccountByName(String accountName) {
        List<Account> accounts = jdbcTemplate.query("select * from account where name = ?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        return accounts.get(0);
    }

    @Override
    public void updateAccount(Account account) {
        jdbcTemplate.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
    }
}

IAccountService 接口与AccountServiceImpl实现类

public interface IAccountService {

    /**
     * 转账
     * @param sourceName    转成账户名称
     * @param targetName    转入账户名称
     * @param money         转账金额
     */
    void transfer(String sourceName, String targetName, BigDecimal money);
}


@Service(value = "accountService")
//只读型事务的配置
@Transactional(propagation= Propagation.SUPPORTS,readOnly=true)
// 可读可写型事务的配置
// @Transactional(propagation=Propagation.REQUIRED)
public class AccountServiceImpl implements IAccountService{

    @Autowired
    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

   	//读写型事务配置
    @Transactional(propagation= Propagation.REQUIRED,readOnly=false)
    @Override
    public void transfer(String sourceName, String targetName, BigDecimal money) {
            //1根据名称查询转出账户
            Account source = accountDao.findAccountByName(sourceName);
            //2根据名称查询转入账户
            Account target = accountDao.findAccountByName(targetName);
            //3转出账户减钱
            source.setMoney(source.getMoney().subtract(money));
            //4转入账户加钱
            target.setMoney(target.getMoney().add(money));
            //5.更新转出账户
            accountDao.updateAccount(source);

           // int i=1/0;

            //6更新转入账户
            accountDao.updateAccount(target);
    }
}

注意:默认情况下aop只捕获 Runtimeexception 的异常,但可以通过配置来捕获特定的异常并回 滚

4.执行测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:bean.xml")
public class AccountServiceTest {

    @Autowired
    private  IAccountService as;

    @Test
    public  void testTransfer(){
        as.transfer("A","B", BigDecimal.valueOf(100));

    }

}

四、基于纯注解的声明式事务控制

1.添加依赖

   <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.2.8.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.6</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
        </dependency>
    </dependencies>

2.编写代码

Account实体对象

public class Account implements Serializable {

    private Integer id;
    private String name;
    private BigDecimal money;

	//getter and setter
}

IAccountDao 接口与AccountDaoImpl实现类

public interface IAccountDao {

    /**
     * 根据名称查询账户
     * @param accountName
     * @return
     */
    Account findAccountByName(String accountName);

    /**
     * 更新账户
     * @param account
     */
    void updateAccount(Account account);
}


@Repository("accountDao")
public class AccountDaoImpl implements IAccountDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;
   
    @Override
    public Account findAccountByName(String accountName) {
        List<Account> accounts = jdbcTemplate.query("select * from account where name = ?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        return accounts.get(0);
    }

    @Override
    public void updateAccount(Account account) {
        jdbcTemplate.update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
    }
}

IAccountService 接口与AccountServiceImpl实现类

public interface IAccountService {

    /**
     * 转账
     * @param sourceName    转成账户名称
     * @param targetName    转入账户名称
     * @param money         转账金额
     */
    void transfer(String sourceName, String targetName, BigDecimal money);
}


@Service(value = "accountService")
//只读型事务的配置
@Transactional(propagation= Propagation.SUPPORTS,readOnly=true)
public class AccountServiceImpl implements IAccountService{

    @Autowired
    private IAccountDao accountDao;

    public void setAccountDao(IAccountDao accountDao) {
        this.accountDao = accountDao;
    }

   	//读写型事务配置
    @Transactional(propagation= Propagation.REQUIRED,readOnly=false)
    @Override
    public void transfer(String sourceName, String targetName, BigDecimal money) {
            //1根据名称查询转出账户
            Account source = accountDao.findAccountByName(sourceName);
            //2根据名称查询转入账户
            Account target = accountDao.findAccountByName(targetName);
            //3转出账户减钱
            source.setMoney(source.getMoney().subtract(money));
            //4转入账户加钱
            target.setMoney(target.getMoney().add(money));
            //5.更新转出账户
            accountDao.updateAccount(source);

           // int i=1/0;

            //6更新转入账户
            accountDao.updateAccount(target);
    }
}

3.数据库相关配置

jdbcConfig.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/demo
jdbc.username=root
jdbc.password=123456
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    /**
     * 创建JdbcTemplate
     * @param dataSource
     * @return
     */
    @Bean(name="jdbcTemplate")
    public JdbcTemplate createJdbcTemplate(DataSource dataSource){
        return new JdbcTemplate(dataSource);
    }

    /**
     * 创建数据源对象
     * @return
     */
    @Bean(name="dataSource")
    public DataSource createDataSource(){
        DriverManagerDataSource ds = new DriverManagerDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(username);
        ds.setPassword(password);
        return ds;
    }
}

4.配置事务管理器对象

public class TransactionConfig {

    /**
     * 用于创建事务管理器对象
     * @param dataSource
     * @return
     */
    @Bean(name="transactionManager")
    public PlatformTransactionManager createTransactionManager(DataSource dataSource){
        return new DataSourceTransactionManager(dataSource);
    }
}

5.spring配置类,替代bean.xml

@Configuration
@ComponentScan("cn.ybzy")
@Import({JdbcConfig.class,TransactionConfig.class})
@PropertySource("jdbcConfig.properties")
@EnableTransactionManagement
public class SpringConfiguration {
}

6.执行测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes= SpringConfiguration.class)
public class AccountServiceTest {

    @Autowired
    private  IAccountService as;

    @Test
    public  void testTransfer(){
        as.transfer("A","B",BigDecimal.valueOf(100));

    }

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/137128.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!