1. 程式人生 > >自己動手實現簡單的事務管理(動態代理+註解)一

自己動手實現簡單的事務管理(動態代理+註解)一

使用原生的servlet,沒有使用框架。運用動態代理技術手動實現service層的事務管理。並增加註解功能,用於查詢時無需事務管理。
事務管理需要保證連線Connection的一致,即dao層和service層的connection是同一個,這就需要用到ThreadLocal處理。直接上程式碼:

public class ThreadLocalJDBCUtils {
    private static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
    private static DataSource dataSource;
    static
{ try { //手動載入配置檔案,初始化druid連線池 Properties pro = new Properties(); InputStream in = ThreadLocalJDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"); pro.load(in); dataSource = DruidDataSourceFactory.createDataSource(pro); } catch
(IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } /** * 獲得連線池方法 * @return 資料連線池 */ public static DataSource getDataSource(){ return dataSource; } /** * 獲得連線物件方法 * @return
連線物件 */
public static Connection getConnection() { try { return dataSource.getConnection(); } catch (SQLException e) { throw new RuntimeException("獲取連線失敗"); } } /** * 獲得與執行緒繫結的connection * @return connection */ public static Connection getCurrentConnection() { Connection connection = threadLocal.get(); if(connection==null){ connection = getConnection(); threadLocal.set(connection); } return connection; } /** * 開啟事務 */ public static void beginTransaction(){ try { getCurrentConnection().setAutoCommit(false); } catch (SQLException e) { throw new RuntimeException("開啟事務失敗"); } } /** * 回滾事務 */ public static void rollback(){ try { getCurrentConnection().rollback(); } catch (SQLException e) { throw new RuntimeException("回滾事務失敗"); } } /** * 提交事務 */ public static void commit(){ try { getCurrentConnection().commit();//事務提交 } catch (SQLException e) { throw new RuntimeException("提交事務失敗"); } } /** * 釋放資源 */ public static void close(){ Connection currentConnection = getCurrentConnection(); try { currentConnection.close(); threadLocal.remove();//從執行緒中刪除 } catch (SQLException e) { throw new RuntimeException("釋放資源失敗"); } } }

使用了druid連線池,druid.properties
配置如下:

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///test01
username=root
password=123
initialSize=5
maxActive=10
maxWait=3000

說明:每次使用此工具類時使用getCurrentConnection(),獲得與執行緒繫結的連線物件。第一次,執行緒中沒有connection時從連線池中獲得連線並存到執行緒中。釋放資源時把連線從執行緒中移除。重點不在於此,工具類直接複製也行。注意配置好自己的資料庫。
測試utils,列印connection,沒有報錯打印出地址說明是成功的

public class UtilsTest {
    public static void main(String[] args) {
        Connection connection = ThreadLocalJDBCUtils.getCurrentConnection();
        System.out.println(connection);
    }
}

這裡寫圖片描述