04.dbutils的模擬實現(xiàn)

dbutils的模擬實現(xiàn)

模擬DbUtils(QueryRunner)的實現(xiàn)恶耽,獲取一個數(shù)據(jù)庫連接(池),實現(xiàn)增刪改查操作聂儒,并實現(xiàn)結(jié)果集的簡單封裝(要求數(shù)據(jù)庫查詢結(jié)果的列名與bean的屬性名相同)

一灼擂、工具實現(xiàn)

1.工具使用類DBAssit.java

package com.itheima.dbassit;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DBAssit {

    private DataSource dataSource;

    public DBAssit(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    /** 執(zhí)行增刪改的方法 */
    public int update(String sql,  Object... params) {
        Connection conn = null;
        PreparedStatement pstm = null;
        try {
            // 1. 得到連接
            conn = dataSource.getConnection();

            // 2. 使用連接好參數(shù)的sql語句創(chuàng)建預(yù)處理對象
            pstm = conn.prepareStatement(sql);

            // 3. 得到sql語句參數(shù)的源信息(有幾個層參數(shù),都什么類型的等)
            ParameterMetaData pmd = pstm.getParameterMetaData();

            // 4. 判斷語句中參數(shù)的個數(shù)和方法參數(shù)params的個數(shù)是否一致
            int parameterCount = pmd.getParameterCount();
            // 如果需要參數(shù)焰盗,則開始判斷
            if (parameterCount > 0) {
                if(params == null){
                    throw new NullPointerException("沒有sql語句執(zhí)行必須的參數(shù)");
                }
                if(params.length != parameterCount) {
                    throw new RuntimeException("參數(shù)的參數(shù)個數(shù)有誤璧尸!");
                }
            }
            // 5. 給sql語句的參數(shù)賦值
            for(int i=0;i<parameterCount;i++){
                pstm.setObject(i+1, params[i]);
            }
            // 6. 執(zhí)行語句
            int res = pstm.executeUpdate();
            // 7. 返回執(zhí)行結(jié)果
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(conn, pstm, null);
        }
    }

    /** 查詢的方法 */
    public Object query(String sql, ResultSetHandler rsh, Object... params) {
        Connection conn = null;
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try {
            // 1. 得到連接
            conn = dataSource.getConnection();

            // 2. 使用連接好參數(shù)的sql語句創(chuàng)建預(yù)處理對象
            pstm = conn.prepareStatement(sql);

            // 3. 得到sql語句參數(shù)的源信息(有幾個層參數(shù),都什么類型的等)
            ParameterMetaData pmd = pstm.getParameterMetaData();

            // 4. 判斷語句中參數(shù)的個數(shù)和方法參數(shù)params的個數(shù)是否一致
            int parameterCount = pmd.getParameterCount();
            // 如果需要參數(shù)熬拒,則開始判斷
            if (parameterCount > 0) {
                if(params == null){
                    throw new NullPointerException("沒有sql語句執(zhí)行必須的參數(shù)");
                }
                if(params.length != parameterCount) {
                    throw new RuntimeException("參數(shù)的參數(shù)個數(shù)有誤爷光!");
                }
            }
            // 5. 給sql語句的參數(shù)賦值
            for(int i=0;i<parameterCount;i++){
                pstm.setObject(i+1, params[i]);
            }
            rs = pstm.executeQuery();

            /** 封裝方法需要自己實現(xiàn) */
            return rsh.handle(rs);

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(conn, pstm, null);
        }

    }

    private void release(Connection conn, PreparedStatement pstm, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (pstm != null) {
            try {
                pstm.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

}

2. 結(jié)果集封裝接口

  1. ResultSetHandler.java
package com.itheima.dbassit;

import java.sql.ResultSet;

public interface ResultSetHandler<T> {

    /** 結(jié)果集封裝的方法 */
    Object handle(ResultSet rs);
}
  1. BeanHandler.java實現(xiàn)類
package com.itheima.dbassit.resultSetHandler;

import com.itheima.dbassit.ResultSetHandler;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

/** 有點 */
public class BeanHandler<T> implements ResultSetHandler<T> {

    /** 被封裝的實體類的字節(jié)碼對象 */
    private Class<T> domainClass;

    public BeanHandler(Class<T> domainClass) {
        this.domainClass = domainClass;
    }

    /** 結(jié)果集封裝的具體實現(xiàn)
     * 此類實現(xiàn)的是吧一個結(jié)果集rs封裝到一個指定的實體類對象中
     * 使用要求:(為了方便)
     *      實體類中的屬性必須和表中的列名一致(sql語句查詢出來的列名一致)
     *
     *      */
    public T handle(ResultSet rs) {
        try {
            // 1. 創(chuàng)建一個實體類對象
            T bean = domainClass.newInstance();

            // 2. 判斷是否有結(jié)果集
            if(rs.next()) {
                // 3. 得到結(jié)果集rs中所有的列名
                // 想要得到列名,得先得到結(jié)果集的源信息
                ResultSetMetaData rsmd = rs.getMetaData();

                // 得到源信息之后澎粟,還需要得到多少列
                int columnCount = rsmd.getColumnCount();

                // 遍歷列數(shù)
                for (int i = 1; i<=columnCount; i++) {
                    // 得到每列的名稱
                    String columnName = rsmd.getColumnName(i);
                    // 列名就是實體類的屬性名稱蛀序,于是集可以使用列名得到實體類中屬性的【描述器】
                    PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass); //定義實體類中定義的描述器
                    // 獲取屬性的寫入方法(set方法)
                    Method method = pd.getWriteMethod();
                    // 獲取當前列名所對應(yīng)的值
                    Object columnValue = rs.getObject(columnName);
                    // 通過執(zhí)行方法吧得到的值給屬性附上
                    method.invoke(bean, columnValue);
                }
            }
            // 返回封裝的對象
            return bean;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

  1. BeanListHandler.java 實現(xiàn)類
package com.itheima.dbassit.resultSetHandler;

import com.itheima.dbassit.ResultSetHandler;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;

public class BeanListHandler<T> implements ResultSetHandler<T> {

    /** 被封裝的實體類的字節(jié)碼對象 */
    private Class<T> domainClass;

    public BeanListHandler(Class<T> domainClass) {
        this.domainClass = domainClass;
    }

    /** 結(jié)果集封裝的具體實現(xiàn)
     * 此類實現(xiàn)的是吧一個結(jié)果集rs封裝到一個指定的實體類對象中
     * 使用要求:(為了方便)
     *      實體類中的屬性必須和表中的列名一致(sql語句查詢出來的列名一致)
     *
     *      */
    public List<T> handle(ResultSet rs) {
        try {

            List<T> list = new ArrayList<T>();

            // 2. 判斷是否有結(jié)果集
            while(rs.next()) {

                // 1. 創(chuàng)建一個實體類對象
                T bean = domainClass.newInstance();

                // 3. 得到結(jié)果集rs中所有的列名
                // 想要得到列名,得先得到結(jié)果集的源信息
                ResultSetMetaData rsmd = rs.getMetaData();

                // 得到源信息之后活烙,還需要得到多少列
                int columnCount = rsmd.getColumnCount();

                // 遍歷列數(shù)
                for (int i = 1; i<=columnCount; i++) {
                    // 得到每列的名稱
                    String columnName = rsmd.getColumnName(i);
                    // 列名就是實體類的屬性名稱徐裸,于是集可以使用列名得到實體類中屬性的【描述器】
                    PropertyDescriptor pd = new PropertyDescriptor(columnName, domainClass); //定義實體類中定義的描述器
                    // 獲取屬性的寫入方法(set方法)
                    Method method = pd.getWriteMethod();
                    // 獲取當前列名所對應(yīng)的值
                    Object columnValue = rs.getObject(columnName);
                    // 通過執(zhí)行方法吧得到的值給屬性附上
                    method.invoke(bean, columnValue);
                }
                list.add(bean);
            }
            // 返回封裝的對象
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

3.被封裝的javaBean

public class MyCount {

    private int id;
    private String name;
    private Float money;
    ...

二、測試方法

public class Main {

    public static void main(String[] args) throws Exception {
        ComboPooledDataSource ds = new ComboPooledDataSource();
        ds.setDriverClass("com.mysql.jdbc.Driver");
        ds.setJdbcUrl("jdbc:mysql:///spring_01");
        ds.setUser("root");
        ds.setPassword("abc123");

        DBAssit dbAssit = new DBAssit((DataSource)ds);
        Object obj = dbAssit.query("select * from account where id = ?",
                new BeanHandler(MyCount.class), 1);
        System.out.println(obj);
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末啸盏,一起剝皮案震驚了整個濱河市重贺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌回懦,老刑警劉巖气笙,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怯晕,居然都是意外死亡潜圃,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門贫贝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秉犹,“玉大人,你說我怎么就攤上這事稚晚〕缍拢” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵客燕,是天一觀的道長鸳劳。 經(jīng)常有香客問我,道長也搓,這世上最難降的妖魔是什么赏廓? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任涵紊,我火速辦了婚禮,結(jié)果婚禮上幔摸,老公的妹妹穿的比我還像新娘摸柄。我一直安慰自己,他們只是感情好既忆,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布驱负。 她就那樣靜靜地躺著,像睡著了一般患雇。 火紅的嫁衣襯著肌膚如雪跃脊。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天苛吱,我揣著相機與錄音酪术,去河邊找鬼。 笑死翠储,一個胖子當著我的面吹牛绘雁,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播援所,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼咧七,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了任斋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤耻涛,失蹤者是張志新(化名)和其女友劉穎废酷,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抹缕,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡澈蟆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了卓研。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趴俘。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖奏赘,靈堂內(nèi)的尸體忽然破棺而出寥闪,到底是詐尸還是另有隱情,我是刑警寧澤磨淌,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布疲憋,位于F島的核電站,受9級特大地震影響梁只,放射性物質(zhì)發(fā)生泄漏缚柳。R本人自食惡果不足惜埃脏,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望秋忙。 院中可真熱鬧彩掐,春花似錦、人聲如沸灰追。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽监嗜。三九已至谐檀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間裁奇,已是汗流浹背桐猬。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留刽肠,地道東北人溃肪。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像音五,于是被迫代替她去往敵國和親惫撰。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容