Spring总结十:事务案例

数据库表Account:

 导包:

    <dependencies>
        <!--测试-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>
        <!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <!--连接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <!--spring-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <!--日志-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>
    </dependencies>
View Code

tx,aop配置声名式事务:

首先编写我们的dao和service代码:

public class AccountDao extends JdbcDaoSupport {
    //出账
    public void rollout(String name, double money) {
        String sql = "update account set money=money-? where name=?";
        super.getJdbcTemplate().update(sql, money, name);
    }

    //入账
    public void shiftto(String name, double money) {
        String sql = "update account set money=money+? where name=?";
        super.getJdbcTemplate().update(sql, money, name);
    }
}
public class AccountService {
    private AccountDao accountDao;

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

    //转账
    public void transfer(String outName, String inName, double money) {
        accountDao.rollout(outName, money);
        //int i = 1 / 0;
        accountDao.shiftto(inName, money);
    }
}

添加数据库配置文件jdbc.properties:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/temp_db?useUnicode=true&characterEncoding=utf8&autoReconnect=true
  &allowMultiQueries=true
jdbc.username=root
jdbc.password=root

添加并配置spring配置文件applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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
                        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
">
    <!--关联jdbc配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <!--配置c3p0连接池-->
    <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--dao和service-->
    <bean id="accountDao" class="com.zy.dao.AccountDao">
        <!--由于我们的AccountDao继承了JdbcDaoSupport 所以跳过jdbcTemplate 直接设置datasource-->
        <property name="dataSource" ref="c3p0DataSource"></property>
    </bean>
    <bean id="accountService" class="com.zy.service.AccountService">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--定义事务管理器(声明式的事务)-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="c3p0DataSource"></property>
    </bean>
    <!--tx标签配置的拦截器 底层依赖aop环绕通知 所以下面会配置aop切入点和切面-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 配置事务管理属性,TransactionDefinition -->
            <!--
                    name 方法名
                    isolation 隔离级别 默认DEFAULT
                    propagation 传播行为 默认 REQUIRED
                    timeout 超时时间 默认 -1 不超时
                    read-only 是否只读  默认false 不是只读
                    rollback-for 配置一些异常,发生这些异常事务进行回滚
                    no-rollback-for 配置一些异常,发生这些异常,将被忽略,事务仍然进行提交
                 -->
            <!--我们拦截的方法是转账方法 transfer-->
            <tx:method name="transfer"/>
        </tx:attributes>
    </tx:advice>

    <!--配置切入点和切面-->
    <aop:config proxy-target-class="false">
        <aop:advisor advice-ref="txAdvice" pointcut="bean(*Service)"></aop:advisor>
    </aop:config>
</beans>

测试代码:

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

    @Value("#{accountService}")
    AccountService accountService;

    @Test
    public void transfer() throws Exception {
        accountService.transfer("张学友", "刘德华", 100);
    }

}

使用@Transactional注解进行声明式事务管理:

需要加事务的方法上加上注解:

public class AccountService {
    private AccountDao accountDao;

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

    //转账
    @Transactional
    public void transfer(String outName, String inName, double money) {
        accountDao.rollout(outName, money);
        accountDao.shiftto(inName, money);
    }
}

applicationContext.xml修改如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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
                        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
">
    <!--关联jdbc配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
    <!--配置c3p0连接池-->
    <bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driverClassName}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    <!--dao和service-->
    <bean id="accountDao" class="com.zy.dao.AccountDao">
        <!--由于我们的AccountDao继承了JdbcDaoSupport 所以跳过jdbcTemplate 直接设置datasource-->
        <property name="dataSource" ref="c3p0DataSource"></property>
    </bean>
    <bean id="accountService" class="com.zy.service.AccountService">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <!--&lt;!&ndash;定义事务管理器(声明式的事务)&ndash;&gt;-->
    <!--<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">-->
        <!--<property name="dataSource" ref="c3p0DataSource"></property>-->
    <!--</bean>-->
    <!--&lt;!&ndash;tx标签配置的拦截器 底层依赖aop环绕通知 所以下面会配置aop切入点和切面&ndash;&gt;-->
    <!--<tx:advice id="txAdvice" transaction-manager="transactionManager">-->
        <!--<tx:attributes>-->
            <!--&lt;!&ndash; 配置事务管理属性,TransactionDefinition &ndash;&gt;-->
            <!--&lt;!&ndash;-->
                    <!--name 方法名-->
                    <!--isolation 隔离级别 默认DEFAULT-->
                    <!--propagation 传播行为 默认 REQUIRED-->
                    <!--timeout 超时时间 默认 -1 不超时-->
                    <!--read-only 是否只读  默认false 不是只读-->
                    <!--rollback-for 配置一些异常,发生这些异常事务进行回滚-->
                    <!--no-rollback-for 配置一些异常,发生这些异常,将被忽略,事务仍然进行提交-->
                 <!--&ndash;&gt;-->
            <!--&lt;!&ndash;我们拦截的方法是转账方法 transfer&ndash;&gt;-->
            <!--<tx:method name="transfer"/>-->
        <!--</tx:attributes>-->
    <!--</tx:advice>-->

    <!--&lt;!&ndash;配置切入点和切面&ndash;&gt;-->
    <!--<aop:config proxy-target-class="false">-->
        <!--<aop:advisor advice-ref="txAdvice" pointcut="bean(*Service)"></aop:advisor>-->
    <!--</aop:config>-->

    <!--增加注解版 事务管理器-->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

    <!--事务通知依赖于 事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="c3p0DataSource"></property>
    </bean>
</beans>

ok

原文地址:https://www.cnblogs.com/blazeZzz/p/9319959.html