1. 程式人生 > >Spring學習(四)Jdbc連線池交個spring管理和事務操作

Spring學習(四)Jdbc連線池交個spring管理和事務操作

一、連線池的配置交給Spring管理

1,新增jar包

這裡寫圖片描述

2,spring的jdbc連線池配置



<!-- 配置連線池 -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="password"
value="tianyejun" />
<property name="username" value="root" /> <property name="url" value="jdbc:mysql:///springday3" /> </bean> <!-- 配置jdbc的模板類 --> <bean id="JdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name
="dataSource" ref="dataSource">
</property> </bean>

3,測試類


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")

public class Demo1 {

/**
     * 使用ioc的方式
     */
    @Resource(name = "JdbcTemplate")
    private JdbcTemplate JdbcTemplate;

    @Test
public void run2() { // 可以實現對資料庫的cud JdbcTemplate.update("insert into t_account values(null,?,?)", "3343", "1000"); } /** * 資料庫查詢 */ @Test public void runQuery() { //查詢一條資料 AccontBean bean =JdbcTemplate.queryForObject("select * from t_account where id=?", new String[] { "1" }, new MyrowMapper()); System.out.println(bean.toString()); // 查詢所有資料 List<AccontBean> list = (List<AccontBean>) JdbcTemplate.query("select * from t_account",new MyrowMapper()); System.out.println(list); } public class MyrowMapper implements RowMapper<AccontBean> { @Override public AccontBean mapRow(ResultSet rs, int rowNum) throws SQLException { AccontBean bean = new AccontBean(); bean.setName(rs.getString(2)); bean.setPrice(rs.getInt(3)); return bean; } } } }

二、Spring的事物管理

1,事物的特性

原子性 :強調事務的不可分割.
一致性 :事務的執行的前後資料的完整性保持一致.
隔離性 :一個事務執行的過程中,不應該受到其他事務的干擾
永續性 :事務一旦結束,資料就持久到資料庫

2,事物的傳播行為

PROPAGION_XXX :事務的傳播行為

  • 保證同一個事務中

PROPAGATION_REQUIRED:支援當前事務,如果不存在 就新建一個(預設)
PROPAGATION_SUPPORTS:支援當前事務,如果不存在,就不使用事務
PROPAGATION_MANDATORY:支援當前事務,如果不存在,丟擲異常

  • 保證沒有在同一個事務中

PROPAGATION_REQUIRES_NEW: 如果有事務存在,掛起當前事務,建立一個新的事務
PROPAGATION_NOT_SUPPORTED :以非事務方式執行,如果有事務存在,掛起當前事務
PROPAGATION_NEVER : 以非事務方式執行,如果有事務存在,丟擲異常

PROPAGATION_NESTED: 如果當前事務存在,則巢狀事務執行

案例:模擬銀行轉賬漏洞環境

(1)建立業務層


業務層介面類:
public interface AccountServiceInter {
    public void pay(String out, String in, double money);

}

業務層介面實現類

public class AccountServiceImp implements AccountServiceInter {
    private AccountDaoInter acountdao;

    /**
     * 轉賬的方法
     */
    @Override
    public void pay(String out, String in, double money) {
        // 先價錢
        getAcountdao().outMoney(out, money);
        /**
         *這裡人為製造一個異常,造成轉賬出現異常
        */
        int a=10/0;

        // 後加錢
        getAcountdao().inMoney(in, money);
    }

    public AccountDaoInter getAcountdao() {
        return acountdao;
    }

    public void setAcountdao(AccountDaoInter acountdao) {
        this.acountdao = acountdao;
    }

}

(2)建立dao層


dao介面類

public interface AccountDaoInter {
    // 扣錢
    public void outMoney(String out, double money);

    // 加錢
    public void inMoney(String in, double money);

}

dao介面實現類

public class AccountDaoImp extends JdbcDaoSupport implements AccountDaoInter {

    /**
     * 扣錢
     */
    @Override
    public void outMoney(String out, double money) {
        int update = this.getJdbcTemplate().update("update t_account set money=(money-?) where id=?", money, out);
        System.out.println("fdafd" + update);
    }

    /**
     * 加錢
     */
    @Override
    public void inMoney(String in, double money) {
        int update = this.getJdbcTemplate().update("update t_account set money=(money+?) where id=?", money, in);
        System.out.println("fdafd" + update);
    }

}

(3)spring中配置業務層和dao


<!-- 配置連線池 -->
<bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="password" value="tianyejun6" />
    <property name="username" value="root" />
    <property name="url" value="jdbc:mysql:///springday3" />
</bean>


<!-- service業務層 -->

<bean id="accountService"     class="com.itcast.test1.AccountServiceImp">
    <property name="acountdao" ref="accountDaoImp"></property>
</bean>

<!-- 持久層dao -->

<bean id="accountDaoImp" class="com.itcast.test1.AccountDaoImp">
    <property name="dataSource" ref="dataSource" />
</bean>

(4)編寫測試類


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class Test1 {
    @Resource(name = "accountService")
    private AccountServiceInter accountService;
    DataSourceTransactionManager a;
    @Test
    public void run1() {
        accountService.pay("1", "3", 100);
    }

}

總結:上面轉賬過程如果出現異常情況,就會造成轉賬漏洞,所以採用下面AOP轉賬方式

三、spring事務管理採用AOP方式

1,引入jar包

這裡寫圖片描述

2,配置事務管理器 ,開啟事物註解


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

<!-- 開啟註解事務管理 -->
    <tx:annotation-driven 
    transaction-manager="transactionManager"/>

3,配置事務的通知


<!-- 2,配置通知 -->
<tx:advice id="myAdvice" transaction-manager="transactionManager">
    <tx:attributes>
     <!-- 
        isolation="DEFAULT"     隔離級別
        propagation="REQUIRED"  傳播行為
        read-only="false"   只讀
        timeout="-1"        過期時間
        rollback-for=""     -Exception
        no-rollback-for=""  +Exception
    -->
        <tx:method name="pay" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

4,配置AOP


<!--
配置AOP:如果是自己編寫的aop使用<aop:aspect>;
如果使用spring框架提供的通知使用<aop:advisor/>
 -->
<aop:config>
    <aop:advisor advice-ref="myAdvice"
        pointcut="execution(public * com.itcast.test2.AccountServiceImp.pay(..))"/>
</aop:config>

5,實現程式碼

(1)業務層

業務層介面

public interface AccountServiceInter {
    public void pay(String out, String in, double money);

}


業務層介面實現類

/**
 * 
 *@Transactional 新增到類上,該類所有的方法都有事務
 */
@Transactional
public class AccountServiceImp implements AccountServiceInter {
    private AccountDaoInter acountdao;

    /**
     * 轉賬的方法
     */
    @Override
    @Transactional
    public void pay(String out, String in, double money) {
        // 先價錢
        getAcountdao().outMoney(out, money);
//      int a=10/0;
        // 後加錢
        getAcountdao().inMoney(in, money);
    }

    public AccountDaoInter getAcountdao() {
        return acountdao;
    }

    public void setAcountdao(AccountDaoInter acountdao) {
        this.acountdao = acountdao;
    }

}

(2)dao層


dao介面類

public interface AccountDaoInter {
    // 扣錢
    public void outMoney(String out, double money);

    // 加錢
    public void inMoney(String in, double money);

}

dao實現介面類


public class AccountDaoImp extends JdbcDaoSupport implements AccountDaoInter {

    /**
     * 扣錢
     */
    @Override
    public void outMoney(String out, double money) {
        int update = this.getJdbcTemplate().update
        ("update t_account set money=(money-?) where id=?", money, out);
        System.out.println("fdafd" + update);
    }

    /**
     * 加錢
     */
    @Override
    public void inMoney(String in, double money) {
update("update t_account set money=(money+?) where id=?", money, in);
        System.out.println("fdafd" + update);
    }

}

(3)Spring的xml配置


<!-- 配置連線池 -->
<bean id="dataSource"       class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="password" value="tianyejun6" />
    <property name="username" value="root" />
    <property name="url" value="jdbc:mysql:///springday3" />
</bean>

<!-- service業務層 -->

<bean id="accountService" class="com.itcast.test2.AccountServiceImp">
    <property name="acountdao" ref="accountDaoImp"></property>
</bean>

<!-- 持久層dao -->

<bean id="accountDaoImp" class="com.itcast.test2.AccountDaoImp">
    <property name="dataSource" ref="dataSource" />
</bean>

<!-- 1,配置平臺事物管理器 -->

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

<!-- 宣告式事物 -->
<!-- 2,配置通知 -->

<tx:advice id="myAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="pay" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

<!--

配置AOP:如果是自己編寫的aop使用<aop:aspect>;
如果使用spring框架提供的通知使用<aop:advisor/>

 -->

<aop:config>
  <aop:advisor advice-ref="myAdvice"
        pointcut="execution(public * com.itcast.test2.AccountServiceImp.pay(..))"/>
</aop:config>

(4)測試類


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class Test1 {
    @Resource(name = "accountService")
    private AccountServiceInter accountService;
    DataSourceTransactionManager a;
    @Test
    public void run1() {
        accountService.pay("1", "3", 100);
    }

}

(5)原始碼