Spring声明式事务

假设一个人去4s店买车,需要修改数据库中车辆库存和user的余额,选好车后发现没钱肯定不能提车即事务(如果有可以买车不付钱的地方请带上我)

xml文件配置

资源文件

user=root
password=****
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://127.0.0.1:3306/test

initPoolSize=5
maxPoolSize=10
<?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:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
     <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.spring.tx"></context:component-scan>

    <!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    
    <!-- 导入资源文件 src目录下的db.propertier文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <!-- 配置 C3P0 数据源 -->
     <bean id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${user}"></property>
        <property name="password" value="${password}"></property>
        <property name="jdbcUrl" value="${jdbcUrl}"></property>
        <property name="driverClass" value="${driverClass}"></property>

        <property name="initialPoolSize" value="${initPoolSize}"></property>
        <property name="maxPoolSize" value="${maxPoolSize}"></property>
    </bean>
    
    
    <!-- 配置 Spirng 的 JdbcTemplate -->
    <bean id="jdbcTemplate" 
        class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!--  配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 启用事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    

</beans>

Dao类

package com.spring.tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
* 
* @version 创建时间:2017年8月15日 上午6:26:18
* 类说明
*/
@Repository("carDao")
public class CarDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    public int findCarPriceByName(String name) {
        String sql = "select price from car where name = ?";
        return jdbcTemplate.queryForObject(sql, Integer.class, name);
    }
    
    public void updataCarStock(String name) {
        String sql = "select stock from car where name = ?";
        int stock = jdbcTemplate.queryForObject(sql,Integer.class, name);
        if(stock<=0) {
            throw new StockException("库存不足");
        }        
        
        sql = "update car set stock = stock-1 where name = ?";
        jdbcTemplate.update(sql, name);
    }
    
    public void updataUserMoney(String name,int price) {
        String sql = "select money from user where name = ?";
        int money = jdbcTemplate.queryForObject(sql,Integer.class,name);
        if(money<price) {
            throw new MoneyException("穷------");  //QAQ
        }
        sql = "update user set money = ? where name = ?";
        money = money - price;
        jdbcTemplate.update(sql, money,name);
    }
    
}

需要抛出的异常类

package com.spring.tx;
/**
* 
* @version 创建时间:2017年8月15日 上午6:44:14
* 类说明
*/
public class StockException extends RuntimeException {
       //缺少库存
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    public StockException() {
        super();
    }
    public StockException(String massage) {
        // TODO Auto-generated constructor stub
        super(massage);
    }
}


package com.spring.tx;
/**
* 
* @version 创建时间:2017年8月15日 上午6:46:56
* 类说明
*/
public class MoneyException extends RuntimeException{

     /**
     * 
     */
//缺钱
    private static final long serialVersionUID = 1L;

    public MoneyException() {
        // TODO Auto-generated constructor stub
         super();
    }
    public MoneyException(String massage) {
        // TODO Auto-generated constructor stub
         super(massage);
    }
}

Service

package com.spring.tx;
/**
* 
* @version 创建时间:2017年8月15日 上午9:35:45
* 类说明
*/

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("carShopServlet")
public class CarShopServlet {
    
    @Autowired
    private CarDao carDao;
    
    
    //添加事务注解
    @Transactional
    public void purchase(String username, String carname) {
        
        int price = carDao.findCarPriceByName(carname);
        
        carDao.updataCarStock(carname);
        
        carDao.updataUserMoney(username, price);
        
        //要是没事务就可以买车不付钱了
    }

}

Test

package com.spring.tx;

import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.*;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

/**
* 
* @version 创建时间:2017年8月15日 上午7:00:01
* 类说明
*/
public class Test {

    private ApplicationContext ctx = null;
    private CarShopServlet carShopServlet =null;
    
    
    
    {
        ctx = new ClassPathXmlApplicationContext("beans-tx.xml");
        carShopServlet = (CarShopServlet) ctx.getBean("carShopServlet");
    
    }
    @org.junit.Test
    public void testtx() {
        
        
        carShopServlet.purchase("关羽", "福特");
        
        carShopServlet.purchase("关羽", "兰博基尼");
    }
    
    
    
    
    @org.junit.Test
    public void testcon() throws SQLException {//测试是否连上数据库
        // TODO Auto-generated constructor stub
        
        DataSource dataSource = (DataSource) ctx.getBean("dataSource");
        System.out.println(dataSource.getConnection());
        /*JdbcTemplate jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
        System.out.println(jdbcTemplate);*/
    }
    

    

}

运行前数据

 运行后

买了福特 但是买不起兰博基尼

基于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:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    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/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">


    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="com.spring.tx.xml"></context:component-scan>

    <!-- 配置自动为匹配 aspectJ 注解的 Java 类生成代理对象 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    
    <!-- 导入资源文件 -->
    <context:property-placeholder location="classpath:db.properties"/>
    
    <!-- 配置 C3P0 数据源 -->
     <bean id="dataSource"
        class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${user}"></property>
        <property name="password" value="${password}"></property>
        <property name="jdbcUrl" value="${jdbcUrl}"></property>
        <property name="driverClass" value="${driverClass}"></property>

        <property name="initialPoolSize" value="${initPoolSize}"></property>
        <property name="maxPoolSize" value="${maxPoolSize}"></property>
    </bean>
    
    
    <!-- 配置 Spirng 的 JdbcTemplate -->
    <bean id="jdbcTemplate" 
        class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!--  配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 启用事务注解 -->
    <!--  <tx:annotation-driven transaction-manager="transactionManager"/>-->
    
    <!--  配置事务属性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 根据方法名指定事务的属性 -->
            <!-- 事务传播属性 默认为REQUIRES -->
            <tx:method name="purchase" propagation="REQUIRES_NEW"/>
            <tx:method name="get*" read-only="true"/>
            <tx:method name="find*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    
    <!--  配置事务切入点, 以及把事务切入点和事务属性关联起来 -->
    <aop:config>
         <!-- 此包下的所有类的所有方法其实只有purchase一个方法 -->
        <aop:pointcut expression="execution(* com.spring.tx.xml.service.*.*(..))" 
            id="txPointCut"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>    
    </aop:config>

</beans>
原文地址:https://www.cnblogs.com/lusufei/p/7363745.html