Spring基础4——JdbcTemplate和声明式事务控制

  Spring框架的JdbcTemplate是对JDK原生的JDBC做了封装,使用 JdbcTemplate 方便实现对数据库操作。

一、基础案例

1.1、不通过bean.xml文件加载DriverManagerDataSource.class(驱动类)和JDBCTemplate.class

  • JdbcTemplate.class使用构造函数加载DriverManagerDataSource.class类型的对象,并访问mysql数据库
package xxx.xxx.jdbcTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class JDBCTemplate {
   public static void main(String[] args) {
      DriverManagerDataSource driver = new DriverManagerDataSource();
      driver.setDriverClassName("com.mysql.jdbc.Driver");
      driver.setUrl("jdbc:mysql://localhost:3306/spring");
      driver.setUsername("root");
      driver.setPassword("root");

      JdbcTemplate template = new JdbcTemplate(driver);
      template.update("insert into account (name,money)values(?,?)","testJdbcTemplate",172.0);
   }
}
  • JdbcTemplate.class使用set()函加载DriverManagerDataSource.class类型的对象,并访问mysql数据库
package xxx.xxx.jdbcTemplate;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class JDBCTemplate {
   public static void main(String[] args) {
      DriverManagerDataSource driver = new DriverManagerDataSource();
      driver.setDriverClassName("com.mysql.jdbc.Driver");
      driver.setUrl("jdbc:mysql://localhost:3306/spring");
      driver.setUsername("root");
      driver.setPassword("root");

      JdbcTemplate template = new JdbcTemplate();
      template.setDataSource(driver);
      template.update("insert into account (name,money)values(?,?)","testJdbcTemplate",172.0);
   }
}

上述代码的执行结果,如下图所示(数据库的表结构定义和表中的数据):
image

image

1.2、通过bean.xml文件加载DriverManagerDataSource.class(驱动类)和JdbcTemplate.class

  • Maven的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xxx.xxx</groupId>
    <artifactId>Spring04_jdbcTemplate</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <packaging>jar</packaging>

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

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

</project>
  • Spring的bean.xml配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="driver"></constructor-arg>
    </bean>

    <bean id="driver" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

</beans>
  • 通过Spring的ClassPathXmlApplicationContext.class加载bean.xml并获取JdbcTemplate.class类型的对象
package .jdbcTemplate;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class JDBCTemplate2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        JdbcTemplate template =(JdbcTemplate) ac.getBean("jdbcTemplate");
        template.update("insert into account (name,money)values(?,?)","jdbcTemplate_xml",122.0);
    }
}

上述代码的执行结果,如下图所示(数据库的表结构定义和表中的数据):
image
image

二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据

  • Maven的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>xxx.xxx</groupId>
    <artifactId>Spring04_jdbcTemplate</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <packaging>jar</packaging>

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

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

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

</project>
  • Spring的bean.xml配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="driver"></constructor-arg>
    </bean>

    <bean id="driver" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

</beans>
  • 封装对象的实体类Account.class
package xxx.xxx.domain;

import java.io.Serializable;

/**
 * 账户的实体类
 */
public class Account implements Serializable {

    private Integer id;
    private String name;
    private Float money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Float getMoney() {
        return money;
    }

    public void setMoney(Float money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

  • 使用 RowMapper.interface接口的实现类来封装对象
package xxx.xxx.jdbcTemplate;

import xxx.xxx.domain.Account;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class JDBCTemplate3 {
   public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        JdbcTemplate template =(JdbcTemplate) ac.getBean("jdbcTemplate");
        //保存方法
        template.update("insert into account (name,money)values(?,?)","jdbcTemplate_xml",122.0);
        //更新
        template.update("update account set name=?, money=? where id=?", "template_update",211.0,8);
        //删除
        template.update("delete from account where id=?",8 );
        //查询所有
        List<Account> selfRowMapper= template.query("select * from account", new AccountRowMapper());
        for (Account account : selfRowMapper) {
            System.out.println(account);
        }
   }
}
class AccountRowMapper implements RowMapper{
    //RowMapper.interface的实现类AccountRowMapper.class必须重写mapRow()函数,来封装数据,ResultSet对象可以获取每一行数据来进行封装。
   @Override
   public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
      Account account = new Account();
      account.setId(rs.getInt("id"));
      account.setName(rs.getString("name"));
      account.setMoney(rs.getFloat("money"));
      return account;
   }
}

上述代码的执行结果,如下图所示(程序运行结果+数据库的表结构定义+表中的数据):
image
image
image

三、Spring的JdbcTemplate在封装数据时,也可以使用spirng中的org.springframework.jdbc.core.BeanPropertyRowMapper.class来封装数据

  • Maven的pom.xml文件
    同标题二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据
  • Spring的bean.xml配置文件
    同标题二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据
  • 封装对象的实体类Account.class
    同标题二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据
  • 使用Spirng中的org.springframework.jdbc.core.BeanPropertyRowMapper.class来封装数据
package xxx.xxx.jdbcTemplate;

import xxx.xxx.domain.Account;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

public class JDBCTemplate3 {
   public static void main(String[] args) {
      ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
      JdbcTemplate template =(JdbcTemplate) ac.getBean("jdbcTemplate");
        List<Account> accounts = template.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        for (Account account : accounts) {
            System.out.println(account);
        }

        //查询一个
        List<Account> accountList = template.query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),3);
        System.out.println(accountList.isEmpty()?"没有内容":accountList.get(0));

        //聚合函数查询,查询返回一行一列(但是不能使用group by子句)
        Long count = template.queryForObject("select count(*) from account where money>?", Long.class, 1);
        System.out.println(count);
   }
}

上述代码的执行结果,如下图所示(程序运行结果+数据库的表结构定义+表中的数据):
image
image
image
该原理和DbUtils中的BeanListHandler一样

四、可以对标题三中的代码进行优化

  优化步骤如下:
①、创建JdbcTemplateSupport.class,在setDataSource()函数中生成该DataSource数据的JdbcTemplate对象;
②、为了确保JdbcTemplate类的对象一定存在,还可以设置setTemplate()函数,以确保数据,代码如下:

  • Maven的pom.xml文件
    同标题二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据
  • Spring的bean.xml配置文件
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="accountDao" class="xxx.xxx.dao.impl.IAccountDaoImpl2">
        <property name="dataSource" ref="driver"></property>
        <property name="template" ref="jdbcTemplate"></property>
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <constructor-arg name="dataSource" ref="driver"></constructor-arg>
    </bean>

    <bean id="driver" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>
  • 封装对象的实体类Account.class
    同标题二、Spring的JdbcTemplate在封装数据时,可以使用自定义的RowMapper.interface接口的实现类,来封装数据

  • JdbcTemplateSupport.class

package xxx.xxx.dao.impl;

import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

public class JdbcTemplateSupport {
    public JdbcTemplate template;

    public void setTemplate(JdbcTemplate template) {
       this.template = template;
    }

    public JdbcTemplate getJdbcTemplate(){
       return template;
    }

    public void setDataSource(DataSource dataSource){
       if (template == null){
          template = new JdbcTemplate(dataSource);
       }
    }
}
  • dao层的接口和查询类(使用spirng中的org.springframework.jdbc.core.BeanPropertyRowMapper.class来封装数据)
package xxx.xxx.dao;

import xxx.xxx.domain.Account;

public interface IAccountDao {

    public Account findAccountById(Integer accountId);

    public Account findAccountByName(String accountName);

    public void updateAccount(Account account);
}

package xxx.xxx.dao.impl;

import xxx.xxx.dao.IAccountDao;
import xxx.xxx.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import java.util.List;

public class IAccountDaoImpl2 extends JdbcTemplateSupport implements IAccountDao{


   @Override
   public Account findAccountById(Integer accountId) {
      List<Account> accounts = super.getJdbcTemplate().query("select * from account where id = ?", new BeanPropertyRowMapper<Account>(Account.class), accountId);
      return accounts.isEmpty()?null:accounts.get(0);
   }

   @Override
   public Account findAccountByName(String accountName) {
      List<Account> accounts = super.getJdbcTemplate().query("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), accountName);
      if (accounts.isEmpty()){
         return null;
      }else if(accounts.size() > 1){
         throw new RuntimeException("查询结果不唯一");
      }
      return accounts.get(0);
   }

   @Override
   public void updateAccount(Account account) {
      super.getJdbcTemplate().update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
   }
}
  • 测试上述优化代码
package xxx.xxx.jdbcTemplate;

import xxx.xxx.dao.impl.IAccountDaoImpl2;
import xxx.xxx.domain.Account;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class JDBCTemplate5 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        IAccountDaoImpl2 accountDao = ac.getBean("accountDao", IAccountDaoImpl2.class);
        Account accountByName = accountDao.findAccountByName("aaa");
        System.out.println(accountByName);
        System.out.println("-------------");
        Account accountById = accountDao.findAccountById(1);
        System.out.println(accountById);
    }
}

上述代码的执行结果,如下图所示(程序运行结果+数据库的表结构定义+表中的数据):
image
image
image
ps:上述代码中的JdbcTemplateSupport.class其实在spring中也有对应的实现

五、声明式事务控制

  Spring中事务控制的API是PlatformTransactionManager(事务管理器),此接口是 Spring 的事务管理器,它里面提供了我们常用的操作事务的方法,包含以下3个具体操作:
①、获取事务状态信息

TransactionStatus getTransaction(TransactionDefinition definition)

②、提交事务

void commit(TransactionStatus status)

③、回滚事务

void rollback(TransactionStatus status)

在实际开发中,一般使用的是PlatformTransactionManager接口的实现类DataSourceTransactionManager.class,具体的UML关系图,如下所示:
clipboard

TransactionDefinition(定义事务的传播行为,隔离级别,超时时间等)隔离级别的字段,如下所示:
clipboard
传播行为的字段,如下所示:
clipboard

超时时间和是否为只读事务(参考源码中的TIMEOUT_DEFAULT字段和isReadOnly()函数,只表示有这个功能),如下代码所示:

int TIMEOUT_DEFAULT = -1;
boolean isReadOnly();

5.1、声明式事务控制的案例

  • 数据库表结构和表数据
    image
    image

  • 编写实体类

package xxx.xxx.domain;

import java.io.Serializable;
/**
 * 账户的实体类
 */
public class Account implements Serializable {

    private Integer id;
    private String name;
    private Float money;
    
    //省略setter getter方法和toString方法
}
  • 编写dao层的接口和实现类
package xxx.xxx.dao.impl;

import org.springframework.jdbc.core.JdbcTemplate;
import javax.sql.DataSource;

public class JdbcTemplateSupport {
    public JdbcTemplate template;

    public void setTemplate(JdbcTemplate template) {
       this.template = template;
    }

    public JdbcTemplate getJdbcTemplate(){
       return template;
    }

    public void setDataSource(DataSource dataSource){
       if (template == null){
          template = new JdbcTemplate(dataSource);
       }
    }
}
package xxx.xxx.dao;

import xxx.xxx.domain.Account;

public interface IAccountDao {

    public Account findAccountById(Integer accountId);

    public Account findAccountByName(String accountName);

    public void updateAccount(Account account);
}

package xxx.xxx.dao.impl;

import xxx.xxx.dao.IAccountDao;
import xxx.xxx.domain.Account;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import java.util.List;
/**
 * 账户的持久层实现类
 */
public class AccountDaoImpl extends JdbcDaoSupport implements IAccountDao {

    @Override
    public Account findAccountById(Integer accountId) {
        List<Account> accounts = super.getJdbcTemplate().query("select * from account where id = ?",new BeanPropertyRowMapper<Account>(Account.class),accountId);
        return accounts.isEmpty()?null:accounts.get(0);
    }

    @Override
    public Account findAccountByName(String accountName) {
        List<Account> accounts = super.getJdbcTemplate().query("select * from account where name = ?",new BeanPropertyRowMapper<Account>(Account.class),accountName);
        if(accounts.isEmpty()){
            return null;
        }
        if(accounts.size()>1){
            throw new RuntimeException("结果集不唯一");
        }
        return accounts.get(0);
    }

    @Override
    public void updateAccount(Account account) {
        super.getJdbcTemplate().update("update account set name=?,money=? where id=?",account.getName(),account.getMoney(),account.getId());
    }
}
  • 编写service层的接口和实现类(省略接口文件的代码)
package xxx.xxx.service.impl;

import xxx.xxx.dao.IAccountDao;
import xxx.xxx.domain.Account;
import xxx.xxx.service.IAccountService;
/**
 * 账户的业务层实现类
 *
 * 事务控制应该都是在业务层
 */
public class AccountServiceImpl implements IAccountService{

    private IAccountDao accountDao;

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

    @Override
    public Account findAccountById(Integer accountId) {
        return accountDao.findAccountById(accountId);

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

        int i=1/0;

        //6.更新转入账户
        accountDao.updateAccount(target);
    }
}
  • 编写Spring的bean.xml配置文件
<?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">

    <!-- 配置业务层-->
    <bean id="accountService" class="xxx.xxx.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!-- 配置账户的持久层-->
    <bean id="accountDao" class="xxx.xxx.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/spring"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

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

    <!--配置事务通知,引用事务管理器-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--指定事务通知的方法-->
            <tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" read-only="false" ></tx:method>
        </tx:attributes>
    </tx:advice>

    <!--配置aop-->
    <aop:config>
        <!--配置切入点表达式-->
        <aop:pointcut id="pt1" expression="execution(* xxx.xxx.service.impl.AccountServiceImpl.*(..))"></aop:pointcut>
        <!--建立事务的通知和切入点表达式的关系-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"></aop:advisor>
    </aop:config>
</beans>
  • Maven的pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.chelong</groupId>
    <artifactId>Spring04_SpirngTx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>6</source>
                    <target>6</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <packaging>jar</packaging>

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

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

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

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

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

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

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

</project>
  • 测试
package xxx.xxx.test;

import xxx.xxx.service.IAccountService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

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

   @Autowired
   private IAccountService service;

   @Test
   public void testTransfer(){
      service.transfer("aaa","bbb" , 100.0f);
   }
}

测试结果:可以控制住事务,发生异常时事务进行了回滚。

posted @ 2025-12-20 23:15  Carey_ccl  阅读(5)  评论(0)    收藏  举报