DButil框架

對於數據庫的增刪改查等操作已經有框架實現了
DBUtils是java編程中的數據庫操作實用工具,小巧簡單實用。DBUtils封裝了對JDBC的操作,簡化了JDBC操作。可以少寫代碼。

  • 對於數據表的讀操作,他可以把結果轉換成List,Array,Set等java集合,便於程序員操作
  • 對於數據表的寫操作,也變得很簡單(只需寫sql語句)
  • 可以使用數據源,使用JNDI,數據庫連接池等技術來優化性能–重用已經構建好的數據庫連接對象

DBUtils的三個核心對象

  • QueryRunner類
  • ResultSetHandler接口
  • DBUtils類

一、QueryRunner類:QueryRunner中提供對sql語句操作的API.
它主要有三個方法

  • query() 用於執行select
  • update() 用於執行insert update delete
  • batch() 批處理

二、ResultSetHandler接口:用於定義select操作後,怎樣封裝結果集.

三、DbUtils類:它就是一個工具類,定義了關閉資源與事務處理的方法


Dbutils快速入門

導入jar包
創建QueryRunner對象
使用query方法執行select語句
使用ResultSetHandler封裝結果集
使用DbUtils類釋放資源

一、導入jar包
commons-dbutils-1.4.jar,還有mysql的連接驅動,C3P0的jar包
二、創建QueryRunner對象

QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());

三、使用相關方法


QueryRunner對象

QueryRunnerAPI
這裏寫圖片描述
這裏寫圖片描述
一、構造函數:

  • new QueryRunner(); 它的事務可以手動控制。
    也就是說此對象調用的方法(如:query、update、batrch)參數中要有Connection對象。
  • new QueryRunner(DataSource ds); 它的事務是自動控制的。一個sql一個事務。
    此對象調用的方法(如:query、update、batrch)參數中無需Connection對象。

二、方法:
首先附上C3P0util.java

package com.yanglin.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * Created by zeroyoung on 2016/10/29.
 */
public class C3POUtils {

    public static DataSource dataSource = new ComboPooledDataSource();

    public static DataSource getDataSource(){
        return  dataSource;
    }

    public static Connection getConnection(){
        try {
            return dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("創建連接失敗!");
        }
    }
    public static void close(ResultSet rs, Statement st, Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用dbutls包測試CRUD操作:

@Test
    public void testInsert(){
        DataSource dataSource = C3POUtils.getDataSource();
        QueryRunner qr = new QueryRunner(dataSource);
        try {
            int i = qr.update("insert into users(NAME,PASSWORD,email,birthday)values(?,?,?,?)", "tom", "123", "[email protected]", new Date());
            System.out.println(i);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void testupdate(){
        DataSource dataSource = C3POUtils.getDataSource();
        QueryRunner qr = new QueryRunner(dataSource);
        try {
            int i = qr.update("update users set NAME=? where id=?", "sss", 4);
            System.out.println(i);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void testDelete() throws SQLException{
        //創建一個QueryRunner對象
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        qr.update("delete from users where id=?", 4);
    }
    @Test//批處理,插入多條數據
    public void testBatch() throws SQLException{
        //創建一個QueryRunner對象
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());

        Object[][] params = new Object[10][];//高維代表執行多少次sql語句
        for (int i = 0; i < params.length; i++) {
            params[i] = new Object[]{"丟丟"+i,"123","[email protected]",new Date()};//給每次執行的sql語句中的?賦值
        }
        qr.batch("insert into users(NAME,PASSWORD,email,birthday) values(?,?,?,?)", params );
    }

ResultSetHandler接口

ResultSetHandler下的所有結果處理器

  • ArrayHandler:適合取1條記錄。把該條記錄的每列值封裝到一個數組中Object[]
  • ArrayListHandler:適合取多條記錄。把每條記錄的每列值封裝到一個數組中Object[],把數組封裝到一個List中
  • ColumnListHandler:取某一列的數據。封裝到List中。
  • KeyedHandler:取多條記錄,每一條記錄封裝到一個Map中,再把這個Map封裝到另外一個Map中,key爲指定的字段值。
  • MapHandler:適合取1條記錄。把當前記錄的列名和列值放到一個Map中
  • MapListHandler:適合取多條記錄。把每條記錄封裝到一個Map中,再把Map封裝到List中
  • ScalarHandler:適合取單行單列數據
  • BeanHandler:取出一條記錄,封裝到一個bean中
  • BeanListHandler :取出多條記錄,分別分裝到bean當中

測試代碼:

 @Test//ArrayHandler:適合取1條記錄。把該條記錄的每列值封裝到一個數組中Object[]
    public void teseArrayHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        Object[] arr  = qr.query("select * from users", new ArrayHandler());

        for (Object o : arr) {
            System.out.println(o);
        }
    }
    @Test//ArrayListHandler:適合取多條記錄。把每條記錄的每列值封裝到一個數組中Object[],把數組封裝到一個List中
    public void testArrayListHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        List<Object[]> list = qr.query("select * from users", new ArrayListHandler());

        for (Object[] o : list) {
            for (Object os:o) {
                System.out.println(os);
            }
            System.out.println();
        }
    }

    @Test//ColumnListHandler:取某一列的數據。封裝到List中。
    public void testColumnListHandlerr() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        List<Object> list = qr.query("select * from users", new ColumnListHandler(2));

        for (Object o : list) {
            System.out.println(o);
        }
    }

    @Test//KeyedHandler:取多條記錄,每一條記錄封裝到一個Map中,再把這個Map封裝到另外一個Map中,key爲指定的字段值。
    public void testKeyedHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        Map<Object, Map<String, Object>> map = qr.query("select * from users", new KeyedHandler());

        for (Map.Entry<Object,Map<String, Object>> m: map.entrySet()) {
            System.out.println(m.getKey());
            for (Map.Entry<String,Object> mm: m.getValue().entrySet()) {
                System.out.println(mm.getKey()+"------"+mm.getValue());
            }
            System.out.println("------------------");
        }
    }
    @Test//MapHandler:適合取1條記錄。把當前記錄的列名和列值放到一個Map中
    public void testMapHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        Map<String, Object> map = qr.query("select * from users", new MapHandler());

        for (Map.Entry<String,Object> m: map.entrySet()) {
            System.out.println(m.getKey()+"--------------------"+m.getValue());
        }
    }
    @Test//MapListHandler:適合取多條記錄。把每條記錄封裝到一個Map中,再把Map封裝到List中
    public void testMapListHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        List<Map<String,Object>> list = qr.query("select * from users", new MapListHandler());

        for (Map<String, Object> map : list) {
            for (Map.Entry<String, Object> m : map.entrySet()) {
                System.out.println(m.getKey()+"\t"+m.getValue());
            }
            System.out.println("---------------");
        }
    }
    @Test //ScalarHandler:適合取單行單列數據
    public void testScalarHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        Object o = qr.query("select count(*) from users", new ScalarHandler(1));
        System.out.println(o);//long類型的
    }

    @Test //BeanHandler:適合取單行數據封裝到User對象當中,取不到,不會報錯,會返回空
    public void testBeanHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        User user = qr.query("select * from users where id=?", new BeanHandler<User>(User.class),1);
        System.out.println(user);
    }
    @Test //BeanListHandler:取出一個多條記錄封裝到每一個User當中,返回list
    public void testBeanListHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(C3POUtils.getDataSource());
        //List<User> list = qr.query("select * from users where id=?", new BeanListHandler<User>(User.class),1);
        List<User> list = qr.query("select * from users ", new BeanListHandler<User>(User.class));

        System.out.println(list.size());
    }

DBUtils控制事務

當我們需要控制事務的時候,我們就得調用相關帶有Connection的query(),update()等方法了。但是調用事務我們需要一個Connection對象,這個對象的。然而我們在dao的實現曾是這樣的

DataSource dataSource = C3POUtils.getDataSource();
QueryRunner qr = new QueryRunner(dataSource);

雖然我們的C3P0utils當中有getConnection()方法可以得到一個Connection對象,但是我們事務的開啓都是在service當中的。dao層的值提供數據庫的增刪改查等操作,不涉及業務邏輯層。
而且我們也不能在service當中調用C3POUitls,因爲服務不涉及數據庫相關的操作。而且也會有線程安全問題。
這個時候,我們就得需要使用ThreadLocal這個類的
這裏寫圖片描述
這裏寫圖片描述

ThreadLocal類簡單來說就是一個線程局部變量,他可以在線程當中存放局部變量,調用該類的get方法,永遠返回當前線程放入的數據。線程局部變量。

package com.yanglin.utils;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * Created by zeroyoung on 2016/10/30.
 */
public class ManagerThreadLocal {
    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();

    public static Connection getConnection(){
        Connection conn = tl.get();
        if(conn==null){
            conn = C3POUtils.getConnection();
            tl.set(conn);
        }
        return conn;
    }

    /**
     * 開始事務
     */
    public static void BeginTransaction(){
        try {
            getConnection().setAutoCommit(false);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /*
    * 提交事務
    * */
    public static void commit(){
        try {
            getConnection().commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /*
    * 回滾
    * */
    public static  void rollback(){
        try {
            getConnection().rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    /*
    * 釋放資源
    * */
    public static void close(){
        try {
            getConnection().close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

測試使用:

public class AccountDaoImpl implements AccountDao {


    public void updateAccount(String fromname, String toname, double money) throws Exception {
        //創建一個QueryRunner對象
        QueryRunner qr = new QueryRunner(C3P0Util.getDataSource());
        qr.update("update account set money=money-? where name=?",money,fromname);
        qr.update("update account set money=money+? where name=?",money,toname);
    }

    public void updateAccout(Account account) throws Exception {
        QueryRunner qr = new QueryRunner();
        qr.update(ManagerThreadLocal.getConnection(),"update account set money=? where name=?",account.getMoney(),account.getName());
    }

    public Account findAccountByName(String name) throws Exception {
        QueryRunner qr = new QueryRunner();
        return qr.query(ManagerThreadLocal.getConnection(),"select * from account where name=?", new BeanHandler<Account>(Account.class),name);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章