24、jdbc入門3

guanhang89發表於2016-06-11

後設資料

在jdbc中獲取資料庫的定義,例如:資料庫、表、列的定義資訊。就用到後設資料。
在jdbc中可以使用: 資料庫後設資料、引數後設資料、結果集後設資料
(後設資料定義相關api,  ..MetaData)
public class App {

    //1. 資料庫後設資料
    @Test
    public void testDB() throws Exception {
        // 獲取連線
        Connection conn = JdbcUtil.getConnection();
        // 獲取資料庫後設資料
        DatabaseMetaData metaData = conn.getMetaData();// alt + shift + L  快速獲取方法返回值

        System.out.println(metaData.getUserName());
        System.out.println(metaData.getURL());
        System.out.println(metaData.getDatabaseProductName());
    }

    //2. 引數後設資料
    @Test
    public void testParams() throws Exception {
        // 獲取連線
        Connection conn = JdbcUtil.getConnection();
        // SQL
        String sql = "select * from dept where deptid=? and deptName=?";
        // Object[] values = {"tom","888"};

        PreparedStatement pstmt = conn.prepareStatement(sql);
        // 引數後設資料
        ParameterMetaData p_metaDate = pstmt.getParameterMetaData();
        // 獲取引數的個數
        int count = p_metaDate.getParameterCount();


        // 測試
        System.out.println(count);
    }

    // 3. 結果集後設資料
    @Test
    public void testRs() throws Exception {
        String sql = "select * from dept ";

        // 獲取連線
        Connection conn = JdbcUtil.getConnection();
        PreparedStatement pstmt = conn.prepareStatement(sql);
        ResultSet rs = pstmt.executeQuery();
        // 得到結果集後設資料(目標:通過結果集後設資料,得到列的名稱)
        ResultSetMetaData rs_metaData = rs.getMetaData();

        // 迭代每一行結果
        while (rs.next()) {
            // 1. 獲取列的個數
            int count = rs_metaData.getColumnCount();
            // 2. 遍歷,獲取每一列的列的名稱
            for (int i=0; i<count; i++) {
                // 得到列的名稱
                String columnName = rs_metaData.getColumnName(i + 1);
                // 獲取每一行的每一列的值
                Object columnValue = rs.getObject(columnName);
                // 測試
                System.out.print(columnName + "=" + columnValue + ",");
            }
            System.out.println();
        }

    }
}

Dao操作的提取

Dao操作通用的步驟:

0.  寫SQL語句
1.  獲取連線
2.  建立stmt
3.  執行sql
    a)  更新
    b)  查詢
4.  關閉/異常

通過dao:

1.  更新
String sql = “select * from admin”;
String sql = “select * from admin  where  id=?  And pwd =?”;
public void update(String sql, Object[]  paramValues);

2.  查詢
String sql = “select * from admin”;
String sql = “select * from admin  where  id=?  And pwd =?”;
// 傳入的什麼型別的物件,就封裝為什麼型別
// 要求: 列的名稱,要與指定型別的物件的屬性名稱一樣
Public    List<T>    query  (String sql , Object[] paramValues ,  Class<T> clazz);
T  t;  // 物件賦值

/**
 * 通用的dao,自己寫的所有的dao都繼承此類;
 * 此類定義了2個通用的方法:
 *  1. 更新
 *  2. 查詢
 * @author Jie.Yuan
 *
 */
public class BaseDao {

    // 初始化引數
    private Connection con;
    private PreparedStatement pstmt;
    private ResultSet rs;

    /**
     * 更新的通用方法
     * @param sql   更新的sql語句(update/insert/delete)
     * @param paramsValue  sql語句中佔位符對應的值(如果沒有佔位符,傳入null)
     */
    public void update(String sql,Object[] paramsValue){

        try {
            // 獲取連線
            con = JdbcUtil.getConnection();
            // 建立執行命令的stmt物件
            pstmt = con.prepareStatement(sql);
            // 引數後設資料: 得到佔位符引數的個數
            int count = pstmt.getParameterMetaData().getParameterCount();

            // 設定佔位符引數的值
            if (paramsValue != null && paramsValue.length > 0) {
                // 迴圈給引數賦值
                for(int i=0;i<count;i++) {
                    pstmt.setObject(i+1, paramsValue[i]);
                }
            }
            // 執行更新
            pstmt.executeUpdate();

        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JdbcUtil.closeAll(con, pstmt, null);
        }
    }

    /**
     * 查詢的通用方法
     * @param sql
     * @param paramsValue
     */
    public <T> List<T> query(String sql, Object[] paramsValue,Class<T> clazz){

        try {
            // 返回的集合
            List<T> list = new ArrayList<T>();
            // 物件
            T t = null;

            // 1. 獲取連線
            con = JdbcUtil.getConnection();
            // 2. 建立stmt物件
            pstmt = con.prepareStatement(sql);
            // 3. 獲取佔位符引數的個數, 並設定每個引數的值
            int count = pstmt.getParameterMetaData().getParameterCount();
            if (paramsValue != null && paramsValue.length > 0) {
                for (int i=0; i<paramsValue.length; i++) {
                    pstmt.setObject(i+1, paramsValue[i]);
                }
            }
            // 4. 執行查詢
            rs = pstmt.executeQuery();
            // 5. 獲取結果集後設資料
            ResultSetMetaData rsmd = rs.getMetaData();
            // ---> 獲取列的個數
            int columnCount = rsmd.getColumnCount();

            // 6. 遍歷rs
            while (rs.next()) {
                // 要封裝的物件
                t = clazz.newInstance();

                // 7. 遍歷每一行的每一列, 封裝資料
                for (int i=0; i<columnCount; i++) {
                    // 獲取每一列的列名稱
                    String columnName = rsmd.getColumnName(i + 1);
                    // 獲取每一列的列名稱, 對應的值
                    Object value = rs.getObject(columnName);
                    // 封裝: 設定到t物件的屬性中  【BeanUtils元件】
                    BeanUtils.copyProperty(t, columnName, value);               
                }

                // 把封裝完畢的物件,新增到list集合中
                list.add(t);
            }

            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JdbcUtil.closeAll(con, pstmt, rs);
        }
    }
}



public class AdminDao extends BaseDao {

    // 刪除
    public void delete(int id) {
        String sql = "delete from admin where id=?";
        Object[] paramsValue = {id};
        super.update(sql, paramsValue);
    }

    // 插入
    public void save(Admin admin) {
        String sql = "insert into admin (userName,pwd) values (?,?)";
        Object[] paramsValue = {admin.getUserName(),admin.getPwd()};
        super.update(sql, paramsValue);
    }

    // 查詢全部
    public List<Admin> getAll(){
        String sql = "select * from admin";
        List<Admin> list = super.query(sql, null, Admin.class);
        return list;
    }

    // 根據條件查詢(主鍵)
    public Admin findById(int id){
        String sql = "select * from admin where id=?";
        List<Admin> list = super.query(sql, new Object[]{id}, Admin.class);
        return  (list!=null&&list.size()>0) ? list.get(0) : null;
    }

}

DbUtils

commons-dbutils 是 Apache 組織提供的一個開源 JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,並且使用dbutils能極大簡化jdbc編碼的工作量,同時也不會影響程式的效能。因此dbutils成為很多不喜歡hibernate的公司的首選。

DbUtils元件:

  1. 簡化jdbc操作
  2. 下載元件,引入jar檔案 : commons-dbutils-1.6.jar

例項:

|-- DbUtils   關閉資源、載入驅動
|-- QueryRunner   元件的核心工具類:定義了所有的與資料庫操作的方法(查詢、更新)
    Int  update(Connection conn, String sql, Object param);   執行更新帶一個佔位符的sql
Int  update(Connection conn, String sql, Object…  param); 執行更新帶多個佔位符的sql
Int[]  batch(Connection conn, String sql, Object[][] params)        批處理
T  query(Connection conn ,String sql, ResultSetHandler<T> rsh, Object... params)   查詢方法


Int  update( String sql, Object param);  
Int  update( String sql, Object…  param); 
Int[]  batch( String sql, Object[][] params)       
注意: 如果呼叫DbUtils元件的運算元據庫方法,沒有傳入連線物件,那麼在例項化QueryRunner物件的時候需要傳入資料來源物件:
 QueryRunner qr = new QueryRunner(ds);

DbUtils提供的封裝結果的一些物件:
1)  BeanHandler: 查詢返回單個物件
2)  BeanListHandler: 查詢返回list集合,集合元素是指定的物件
3)  ArrayHandler, 查詢返回結果記錄的第一行,封裝對物件陣列, 即返回:Object[]
4)  ArrayListHandler, 把查詢的每一行都封裝為物件陣列,再新增到list集合中
5)  ScalarHandler 查詢返回結果記錄的第一行的第一列  (在聚合函式統計的時候用)
6)  MapHandler  查詢返回結果的第一條記錄封裝為map

用例:

public class App_query {

    private Connection conn;

    // 一、查詢, 自定義結果集封裝資料
    @Test
    public void testQuery() throws Exception {
        String sql = "select * from admin where id=?";
        // 獲取連線
        conn = JdbcUtil.getConnection();
        // 建立DbUtils核心工具類物件
        QueryRunner qr = new QueryRunner();
        // 查詢
        Admin admin = qr.query(conn, sql, new ResultSetHandler<Admin>() {

            // 如何封裝一個Admin物件
            public Admin handle(ResultSet rs) throws SQLException {
                if (rs.next()) {
                    Admin admin = new Admin();
                    admin.setId(rs.getInt("id"));
                    admin.setUserName(rs.getString("userName"));
                    admin.setPwd(rs.getString("pwd"));
                    return admin;
                }
                return null;
            }

        }, 29);

        // 測試
        System.out.println(admin);
        // 關閉
        conn.close();

    }

    // 二、查詢, 使用元件提供的結果集物件封裝資料

    // 1)BeanHandler: 查詢返回單個物件
    @Test
    public void testQueryOne() throws Exception {
        String sql = "select * from admin where id=?";
        // 獲取連線
        conn = JdbcUtil.getConnection();
        // 建立DbUtils核心工具類物件
        QueryRunner qr = new QueryRunner();
        // 查詢返回單個物件
        Admin admin =  qr.query(conn, sql, new BeanHandler<Admin>(Admin.class), 29);

        System.out.println(admin);
        conn.close();
    }

    // 2)BeanListHandler: 查詢返回list集合,集合元素是指定的物件
    @Test
    public void testQueryMany() throws Exception {
        String sql = "select * from admin";
        conn = JdbcUtil.getConnection();
        QueryRunner qr = new QueryRunner();
        // 查詢全部資料
        List<Admin> list = qr.query(conn, sql, new BeanListHandler<Admin>(Admin.class));

        System.out.println(list);
        conn.close();
    }
    @Test
//  3) ArrayHandler, 查詢返回結果記錄的第一行,封裝對物件陣列, 即返回:Object[]
//  4) ArrayListHandler, 把查詢的每一行都封裝為物件陣列,再新增到list集合中
//  5) ScalarHandler 查詢返回結果記錄的第一行的第一列  (在聚合函式統計的時候用)
//  6) MapHandler  查詢返回結果的第一條記錄封裝為map
    public void testArray() throws Exception {
        String sql = "select * from admin";
        conn = JdbcUtil.getConnection();
        QueryRunner qr = new QueryRunner();
        // 查詢
        //Object[] obj = qr.query(conn, sql, new ArrayHandler());
        //List<Object[]> list = qr.query(conn, sql, new ArrayListHandler());
        //Long num = qr.query(conn, sql, new ScalarHandler<Long>());
        Map<String, Object> map = qr.query(conn,sql, new MapHandler());

        conn.close();
    }
}
public class App_update {

    private Connection conn;

    // 1. 更新
    @Test
    public void testUpdate() throws Exception {
        String sql = "delete from admin where id=?";
        // 連線物件
        conn = JdbcUtil.getConnection();

        // 建立DbUtils核心工具類物件
        QueryRunner qr = new QueryRunner();
        qr.update(conn, sql, 26);

        // 關閉
        DbUtils.close(conn);
    }

    // 2. 批處理
    @Test
    public void testBatch() throws Exception {
        String sql = "insert into admin (userName, pwd) values(?,?)";
        conn = JdbcUtil.getConnection();
        QueryRunner qr = new QueryRunner();
        // 批量刪除
        qr.batch(conn, sql, new Object[][]{ {"jack1","888"},{"jack2","999"}  });

        // 關閉
        conn.close();
    }
}

相關文章