Learn Spring - Spring DAO

1. 概念

  1. Spring的DAO異常體系創建在運行期異常的基礎上,封裝了源異常java

  2. JDBC數據訪問流程:mysql

    • 準備資源spring

    • 啓動事務sql

    • 在事務中執行具體數據訪問操做數據庫

    • 提交/回滾事務apache

    • 關閉資源,處理異常編程

  3. Spring將相同的數據訪問流程固化到模板類中,把數據訪問中固定和變化的部分分開,同時保證模板類是線程安全的。Spring爲不一樣的持久化技術都提供了簡化操做的模板和回調安全

  4. 數據庫事務:原子性,一致性,隔離性和持久性(ACID)併發

  5. 5類數據庫併發問題:app

    • 髒讀:A事務讀取到B事務還沒有提交的數據

    • 不可重複讀:A事務中讀取到B事務已經提交的==更新==數據,即連續兩次讀取結果不一樣

    • 幻讀:A事務讀取B事務的==新增==數據

    • 第一類更新丟失:A事務撤銷時覆蓋了B事務的提交

    • 第二類更新丟失:A事務覆蓋B事務已經提交的數據

  6. JDBC默認狀況下自動提交,即每條執行的SQL語句都對應一個事務,AutoCommit = TRUE

  7. Spring基於ThreadLocal解決有狀態的Connetion的併發問題,事務同步管理器org.springframework.transaction.support.TransactionSynchronizationManager使用ThreadLocal爲不一樣事務線程提供獨立的資源副本

  8. Spring事務管理基於3個接口:TransactionDefinitionTransactionStatusPlatformTransactionManager

  9. Spring爲不一樣持久化技術提供了從TransactionSynchronizationManager獲取對應線程綁定資源的工具類,如DataSourceUtils.getConnection(DataSource dataSource)。模板類在內部經過工具類訪問TransactionSynchronizationManager中的線程綁定資源

  10. Spring經過事務傳播行爲控制當前的事務如何傳播到被嵌套調用的目標服務接口方法中

  11. 使用<tx:annotation-driven transaction-manager="txManager">對標註@Transactional註解的bean進行加工處理,織入事務管理切面

  12. @Transactional註解的屬性

    • 事務傳播行爲:propagation,默認PROPAGATION_REQUIRED,即若是當前沒有事務,就新建一個事務;不然加入到當前事務

    • 事務隔離級別:isolation,默認ISOLATION_DEFAULT

    • 讀寫事務屬性:readOnly

    • 超時時間:timeout

    • 回滾設置:rollbackForrollbackForClassNamenoRollbackFornoRollbackForClassName

  13. 在相同線程中進行相互嵌套調用的事務方法工做於相同的事務中;若是在不一樣線程中,則工做在獨立的事務中

  14. 特殊方法:

    • 註解不能被繼承,因此業務接口中的@Transactional註解不會被業務實現類繼承;方法處的註解會覆蓋類定義處的註解

    • 對於基於接口動態代理的AOP事務,因爲接口方法都是public的,實現類的實現方法必須是public的,同時不能使用static修飾符。所以,能夠經過接口動態代理實施AOP加強、實現Spring事務的方法只能是publicpublic final

    • 基於CGLib動態代理實施AOP的時候,因爲使用finalstaticprivate的方法不能被子類覆蓋,相應的,這些方法不能實施AOP加強,實現事務

    • 不能被Spring進行AOP事務加強的方法不能啓動事務,可是外層方法的事務上下文仍然能夠傳播到這些方法中

2. Spring中使用JDBC編程示例

  • 本地mysql建表

CREATE TABLE `t_user` (
  `user_id` varchar(256) NOT NULL,
  `user_name` varchar(256) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
  • springDAO.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"
    xmlns:p="http://www.springframework.org/schema/p"
    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 ">

    <context:component-scan base-package="com.dao" />

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/sampledb"
        p:username="root"
        p:password="123123" />

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource" />

    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource" />
</beans>
  • User

package com.data;

public class User {

    private String userId;

    private String userName;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

}
  • BaseDAO

package com.dao;

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

public class BaseDAO {

    @Autowired
    protected JdbcTemplate jdbcTemplate;
}
  • UserDAO

package com.dao;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.data.User;
import com.mapper.UserRowMapper;

@Repository
public class UserDAO extends BaseDAO {

    private static final String SQL_GET_USER = "select * from t_user where " + "user_id = ?;";

    private static final String SQL_INSERT_USER = "insert into t_user values(?, ?);";

    private static final String SQL_CLEAN_USER = "delete from t_user where 1=1;";

    @Transactional
    public User getUserById(String userId) {
    return jdbcTemplate.queryForObject(SQL_GET_USER, new Object[]{userId}, new UserRowMapper());
    }

    @Transactional
    public int insertUser(User user) {
        return jdbcTemplate.update(SQL_INSERT_USER, user.getUserId(), user.getUserName());
    }

    @Transactional
    public int cleanUser() {
        return jdbcTemplate.update(SQL_CLEAN_USER);
    }
}
  • UserRowMapper

package com.dao;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import com.data.User;

public class UserRowMapper implements RowMapper<User>{

    public User mapRow(ResultSet rs, int rowNumber) throws SQLException {
        User user = new User();
        user.setUserId(rs.getString("user_id"));
        user.setUserName(rs.getString("user_name"));
        return user;
    }
}
  • BaseTestCase

package com;

import org.junit.Assert;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/springDAO.xml"})
public class BaseTestCase extends Assert {

}
  • TestUserDAO

package com.dao;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import com.BaseTestCase;
import com.data.User;

public class TestUserDAO extends BaseTestCase{

    @Before
    @After
    public void clean() {
        dao.cleanUser();
    }

    @Autowired
    private UserDAO dao;

    @Test
    public void getUserById() {
        User user = new User();
        String id = "id";
        String name = "name";
        user.setUserId(id);
        user.setUserName(name);
        assertEquals(dao.insertUser(user), 1);

        user = dao.getUserById(id);
        assertEquals(user.getUserId(), id);
        assertEquals(user.getUserName(), name);
    }
}
相關文章
相關標籤/搜索