1. 程式人生 > >spring - 淺談spring的事務管理(程式設計式,宣告式(XML版和註解版))

spring - 淺談spring的事務管理(程式設計式,宣告式(XML版和註解版))

事務管理的目的:
              將若干sql語句作為一個整體 , 要麼全部成功 , 要麼全部失敗!

事務套路:
              就是在sql語句前後增加事務!
在這裡插入圖片描述
aop套路 :
              就是將 目的碼 和 增強程式碼 進行 解耦(分離)

 

spring提供的事務管理分為兩類:

一、程式設計式事務管理.(瞭解)

在需要事務管理目的碼中,新增事務管理的程式碼!
(有程式碼侵入事務管理方式 ,現在使用的非常少 )
 
缺點: 將目的碼和增強程式碼耦合在了一起 , 起不到aop的作用!

二、宣告式事務管理.(重點)

底層使用AOP的環繞通知 , 沒有任何程式碼侵入 .
                  (現在推薦使用)

宣告式事務管理兩種實現方式(XML和註解):

1.XML版-事務管理.

匯入依賴jar包 : pom.xml ( 看最後 )

dao層介面: AccountDao.java

public interface AccountDao {
    /**
     * 出賬
     */
    public void out(String outName, double money) throws SQLException;

    /**
     * 入賬
     */
    public void in(String inName, double money) throws SQLException;
}

dao層實現類:AccountDaoImpl01.java

/**
 *   使用xml版 , 對轉賬進行事務管理 .
 */

public class AccountDaoImpl01 extends JdbcDaoSupport implements AccountDao {

    @Override
    public void out(String outName, double money) throws SQLException {
        String sql = "update account set money=money-? where name=?";
        Object[] paramArr = {money, outName};
        getJdbcTemplate().update(sql, paramArr);
    }

    @Override
    public void in(String inName, double money) throws SQLException {
        String sql = "update account set money=money+? where name=?";
        Object[] paramArr = {money, inName};
        getJdbcTemplate().update(sql, paramArr);
    }
}

service層介面:

public interface AccountService {
    /**
     * 轉賬
     */
    public void transfer(String outName, String inName, double money) throws SQLException;
}

service層實現類:

public class AccountServiceImpl01 implements AccountService {

    private AccountDao accountDao;

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

    @Override
    public void transfer(String outName, String inName, double money) throws SQLException {
        // 執行一組sql語句.
        accountDao.out(outName, money);
        // int i= 1/0;
        accountDao.in(inName, money);
    }
}

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_day01
jdbc.username=root
jdbc.password=root

Spring配置檔案: applicationContext_dao.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">
    <!-- 關聯jdbc配置檔案 -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!-- 將連線池交給spring處理 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <!-- 將dao交給spring -->
    <bean id="accountDaoImpl01" class="com.jxj.dao.impl.AccountDaoImpl01">
        <property name="dataSource" ref="dataSource" />
    </bean>
    
</beans>

Spring配置檔案: applicationContext_service.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: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/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">
    <!-- 引入另一個配置檔案 -->
    <import resource="classpath:xml/applicationContext_dao.xml" />

    <!-- 目標類:  將service交給spring -->
    <bean id="accountServiceImpl01" class="com.jxj.service.impl.AccountServiceImpl01">
        <property name="accountDao" ref="accountDaoImpl01" />
    </bean>


    <!-- 增強類:  使用事務管理器進行管理事務. -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:advice id="txAdvice" transaction-manager="transactionManager" >
        <!-- 對哪些方法進行增強事務 -->
        <tx:attributes>
            <tx:method name="transfer"/>
        </tx:attributes>
    </tx:advice>

    <aop:config proxy-target-class="false" >
        <aop:pointcut id="myPoint" expression="execution(* com.jxj.service..*.transfer(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
    </aop:config>
</beans>

測試類:

/**
 *  spring和junit進行整合. 
 */

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

    @Autowired
    @Qualifier("accountServiceImpl01")
    private AccountService accountService;

    @Test
    public void transfer() throws SQLException {
        accountService.transfer("aaa","bbb",200);
    }
} 
2.註解版-事務管理

dao層介面: 同上.
dao層實現類: AccountDaoImpl02 .java

/**
 *   使用註解版 , 對轉賬進行事務管理 .
 */

@Repository
public class AccountDaoImpl02 extends JdbcDaoSupport implements AccountDao {

    // 根據型別注入連線池.
    @Autowired
    public void setDi(DataSource dataSource){
        super.setDataSource(dataSource);
    }

    @Override
    public void out(String outName, double money) throws SQLException {
        String sql = "update account set money=money-? where name=?";
        Object[] paramArr = {money, outName};
        getJdbcTemplate().update(sql, paramArr);
    }

    @Override
    public void in(String inName, double money) throws SQLException {
        String sql = "update account set money=money+? where name=?";
        Object[] paramArr = {money, inName};
        getJdbcTemplate().update(sql, paramArr);
    }
}

service層介面: 同上.
service層實現類: AccountServiceImpl02.java

@Service
public class AccountServiceImpl02 implements AccountService {

    @Autowired
    @Qualifier("accountDaoImpl02")
    private AccountDao accountDao;


    /**
    		給需要增強事務的方法 , 添加註解. (重點) 
     */ 
    @Transactional
    public void transfer(String outName, String inName, double money) throws SQLException {
        // 執行一組sql語句.
        accountDao.out(outName, money);
        // int i= 1/0;
        accountDao.in(inName, money);
    }
}

Spring配置檔案: applicationContext_dao.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">
    <!-- 關聯jdbc配置檔案 -->
    <context:property-placeholder location="classpath:jdbc.properties" />

    <!-- 將連線池交給spring處理 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
    </bean>

    <!-- 通過掃描包的方式 , 將dao交給spring處理 -->
    <context:component-scan base-package="com.jxj.dao" />
</beans>

Spring配置檔案: applicationContext_service.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" 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/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">
    <!-- 引入外部配置檔案 -->
    <import resource="classpath:annotation/applicationContext_dao.xml" />

    <!-- 目標類: service的實現類交給spring-->
    <context:component-scan base-package="com.jxj.service" />

    <!-- 增強類: spring提供的事務管理器. -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 通知spring掃描帶有註解的方法. -->
    <tx:annotation-driven transaction-manager="transactionManager" />
</beans>

測試類:

/**
 *  spring和junit進行整合.
 */

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:annotation/applicationContext_service.xml"})
public class AccountServiceTest {

    @Autowired
    @Qualifier("accountServiceImpl02")
    private AccountService accountService;

    @Test
    public void transfer() throws SQLException {
        accountService.transfer("aaa","bbb",200);
    }
}

依賴: pom.xml

<dependencies>
        <!-- 單元測試 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>

        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
        </dependency>

        <!-- Mybatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
        </dependency>

        <!-- 日誌 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </dependency>

        <!-- MySql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- 連線池 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
    </dependencies>