23、JDBC開發(fā)(6)(OR Mapping)(JavaEE筆記)

一、簡(jiǎn)介

  • 對(duì)象關(guān)系映射
  • 常用映射工具
    • Hibernate用的較多
    • Ibatis用的不多
    • Commons DbUtils(只是對(duì)JDBC簡(jiǎn)單封裝)

二、Apache-DBUtils框架

2.1 簡(jiǎn)介

commons-dbutils是apache組織提供的一個(gè)開源JDBC工具類庫(kù),它是對(duì)JDBC的簡(jiǎn)單封裝,學(xué)習(xí)成本極低,能極大簡(jiǎn)化JDBC編碼的工作量,同時(shí)也不會(huì)影響程序的性能。因此此工具稱為很多不喜歡Hibernate公司的首選。

2.2 工具類(DbUtils類)

提供如關(guān)閉連接、裝載JDBC驅(qū)動(dòng)程序等常規(guī)工作的工具類,里面的所有方法都是靜態(tài)的。主要方法如下:

  • public static void close(…) throws java.sql.SQLException DbUtils類提供了三個(gè)重載的關(guān)閉方法。這些方法檢查所提供的參數(shù)是不是NULL,如果不是的話,它們就關(guān)閉Connection、Statement和ResultSet。

  • public static void closeQuietly(…) 這一類方法不僅能在Connection、Statement和ResultSet為NULL情況下避免關(guān)閉,還能隱藏一些在程序中拋出的SQLEeception。

  • public static void commitAndCloseQuietly(Connection conn)用來(lái)提交連接,然后關(guān)閉連接,并且在關(guān)閉連接時(shí)不拋出SQL異常。

  • public static boolean loadDriver(java.lang.String driverClassName)這一方裝載并注冊(cè)JDBC驅(qū)動(dòng)程序,如果成功就返回true。使用該方法,你不需要捕捉這個(gè)異常ClassNotFoundException

2.3 工具類(QueryRunner類)

  • 該類簡(jiǎn)單化了sql查詢,它與ResultSetHandler組合在一起使用可以完成大部分的數(shù)據(jù)庫(kù)操作,能夠大大的減少編碼量。
  • QueryRunner類提供了兩個(gè)構(gòu)造方法:
    默認(rèn)的構(gòu)造方法和需要一個(gè)javax.sql.DataSource來(lái)作參數(shù)的構(gòu)造方法。
  • 主要方法:
    • public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException執(zhí)行一個(gè)查詢操作,在這個(gè)查詢中,對(duì)象數(shù)組中的每個(gè)元素值被用來(lái)作為查詢語(yǔ)句的置換參數(shù)。該方法會(huì)自行處理 PreparedStatementResultSet的創(chuàng)建和關(guān)閉。
    • public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException 幾乎與第一種方法一樣;唯一的不同在于它不將數(shù)據(jù)庫(kù)連接提供給方法,并且它是從提供給構(gòu)造方法的數(shù)據(jù)源(DataSource) 或使用的setDataSource 方法中重新獲得 Connection。
    • public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException執(zhí)行一個(gè)不需要置換參數(shù)的查詢操作。
    • public int update(Connection conn, String sql, Object[] params) throws SQLException用來(lái)執(zhí)行一個(gè)更新(插入、更新或刪除)操作。
    • public int update(Connection conn, String sql) throws SQLException用來(lái)執(zhí)行一個(gè)不需要置換參數(shù)的更新操作。

2.4 ResultSetHandler接口

  • 該接口用于處理java.sql.ResultSet,將數(shù)據(jù)按要求換行為另一種形式。
  • 提供了一個(gè)單獨(dú)的方法
    Object handle (java.sql.ResultSet .rs)
  • 此接口的實(shí)現(xiàn)類
    • ArrayHandler把結(jié)果集中的第一行數(shù)據(jù)轉(zhuǎn)成對(duì)象數(shù)組。
    • ArrayListHandler把結(jié)果集中的每一行數(shù)據(jù)都轉(zhuǎn)成一個(gè)數(shù)組,再存放到List中。
    • BeanHandler將結(jié)果集中的第一行數(shù)據(jù)封裝到一個(gè)對(duì)應(yīng)的JavaBean實(shí)例中。
    • BeanListHandler將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)對(duì)應(yīng)的JavaBean實(shí)例中,存放到List里。
    • ColumnListHandler將結(jié)果集中某一列的數(shù)據(jù)存放到List中。
    • KeyedHandler(name)將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map里,再把這些map再存到一個(gè)map里,其key為指定的key。大map的key是自己指定,小map的key是列名。
    • MapHandler將結(jié)果集中的第一行數(shù)據(jù)封裝到一個(gè)Map里,key是列名,value就是對(duì)應(yīng)的值。
    • MapListHandler將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map里,然后再存放到List

以下所有示例都在工程(day17

2.5示例一:使用此框架完成基本的增刪改查和批處理操作

首先建立數(shù)據(jù)庫(kù):

CREATE DATABASE day17; 
USE day17;
    
CREATE TABLE USER( id INT PRIMARY KEY AUTO_INCREMENT, NAME VARCHAR(40),
PASSWORD VARCHAR(40), email VARCHAR(60), birthday DATE );

INSERT INTO USER(NAME,PASSWORD,email,birthday)VALUES('zs','123456','zs@sina.com','1980-09-09'); 
INSERT INTO USER(NAME,PASSWORD,email,birthday) VALUES('lisi','123456','lisi@sina.com','1980-09-09'); 
INSERT INTO USER(NAME,PASSWORD,email,birthday) VALUES('wangwu','123456','wangwu@sina.com','1980-09-09');

工具類:JdbcUtils.java

package cn.itcast.utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JdbcUtils {
    private static ComboPooledDataSource ds = null;
    
    static{
        ds = new ComboPooledDataSource();
    }
    
    public static Connection getConnection() throws SQLException{
        
        return ds.getConnection();
    }
    public static DataSource getDataSource(){
        return ds;
    }
}

Demo1.java

package cn.itcast.demo;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import javax.sql.rowset.serial.SerialClob;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.junit.Test;
import cn.itcast.domain.User;
import cn.itcast.utils.JdbcUtils;

public class Demo1 {
    /*
     * 使用dbutils框架完成curd,以及批處理
     */

    @Test
    public void add() throws SQLException {

        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";
        Object params[] = { "ccc", "123", "cc@sina.com", new Date() };
        qr.update(sql, params);
    }

    @Test
    public void delete() throws SQLException {

        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "delete from user where id=?";
        qr.update(sql, 1);
    }

    @Test
    public void update() throws SQLException {
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "update user set name=? where id=?";
        Object params[] = { "ddd", 5 };
        qr.update(sql, params);
    }

    @Test
    public void find() throws SQLException {
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user where id=?";
        Object params[] = { 2 };
        User user = (User) qr.query(sql, params, new BeanHandler(User.class));
        System.out.println(user.getBirthday());
    }

    @Test
    public void getAll() throws SQLException {
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        List list = (List) qr.query(sql, new BeanListHandler(User.class));
        System.out.println(list.size());
    }

    @Test
    public void testBatch() throws SQLException {
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";
        Object params[][] = new Object[10][];
        for (int i = 0; i < 10; i++) {
            params[i] = new Object[] { "aa" + i, "123", "aa@sina.com", new Date() };
        }
        qr.batch(sql, params);
    }

    // 用dbutils完成大數(shù)據(jù)(不建議用)
    /***************************************************************
     create table testclob
     (
        id int primary key auto_increment,
        resume text
     );
     * @throws SQLException 
     * @throws IOException 
********************************************************************/
    
    @Test
    public void testclob() throws SQLException, IOException{
        QueryRunner runner = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "insert into testclob(resume) values(?)";  //clob
        
        //替換參數(shù)
        /*String path = Demo1.class.getClassLoader().getResource("1.txt").getPath();
        Object params[] = {new FileReader(path)};
        */
        
        String path = Demo1.class.getClassLoader().getResource("1.txt").getPath();
        FileReader in = new FileReader(path);
        char[] buffer = new char[(int) new File(path).length()];
        in.read(buffer);
        SerialClob clob = new SerialClob(buffer);
        Object params[] = {clob};
        runner.update(sql, params);
    }
}

說(shuō)明:

  • 1.對(duì)于基本的增刪改查,其使用方式基本一樣。我們只需要將相關(guān)的sql和參數(shù)傳遞進(jìn)去即可使用QueryRunner類幫我們實(shí)現(xiàn)這幾個(gè)基本操作。而對(duì)于查找來(lái)說(shuō),也是需要使用相關(guān)的處理類,如上面使用到的BeanHandler和BeanListHandler類來(lái)進(jìn)行處理,這和我們之前自己編寫框架的思路是一樣的。
  • 2.對(duì)于大數(shù)據(jù),我們不建議使用此框架處理。

2.6實(shí)例二:測(cè)試此框架的處理器

Demo2.java

package cn.itcast.demo;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.KeyedHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;
import cn.itcast.utils.JdbcUtils;

public class Demo2 {
    
    
    //測(cè)試dbutils各種類型的處理器
    
    //把結(jié)果集中的第一行數(shù)據(jù)轉(zhuǎn)成對(duì)象數(shù)組
    @Test
    public void testArrayHandler() throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        Object result[] = (Object[]) qr.query(sql, new ArrayHandler());
        System.out.println(Arrays.asList(result)); //打印出第一行數(shù)據(jù)
    }
    
    //把結(jié)果集中的每一行數(shù)據(jù)都轉(zhuǎn)成一個(gè)數(shù)組,再存放到List中
    @Test
    public void testArrayListHandler() throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        List<Object[]> list = (List) qr.query(sql, new ArrayListHandler());
        for(Object[] o : list){
            System.out.println(Arrays.asList(o));//打印出list中的所有對(duì)象數(shù)據(jù)
        }
    }
    
    //將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)對(duì)應(yīng)的JavaBean實(shí)例中,存放到List里
    @Test
    public void testColumnListHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        
        List list = (List) qr.query(sql, new ColumnListHandler("id"));
        System.out.println(list);//打印出所有id
    }
    
    //將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map里,再把這些map再存到一個(gè)map里,
    //其key為指定的key。大map的key是自己指定,小map的key是列名
    @Test
    public void testKeyedHandler() throws Exception{
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        
        Map<Integer,Map> map = (Map) qr.query(sql, new KeyedHandler("id"));//指定id作為key
        for(Map.Entry<Integer, Map> me : map.entrySet()){
            int  id = me.getKey();
            Map<String,Object> innermap = me.getValue();
            for(Map.Entry<String, Object> innerme : innermap.entrySet()){
                String columnName = innerme.getKey();
                Object value = innerme.getValue();
                System.out.println(columnName + "=" + value);
            }
            System.out.println("----------------");
        }
    }
    
    //將結(jié)果集中的第一行數(shù)據(jù)封裝到一個(gè)Map里,key是列名,value就是對(duì)應(yīng)的值
    @Test
    public void testMapHandler() throws SQLException{
        
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        
        Map<String,Object> map = (Map) qr.query(sql, new MapHandler());
        for(Map.Entry<String, Object> me : map.entrySet()){
            System.out.println(me.getKey() + "=" + me.getValue());
        }
    }
    
    //將結(jié)果集中的每一行數(shù)據(jù)都封裝到一個(gè)Map里,然后再存放到List
    @Test
    public void testMapListHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select * from user";
        List<Map> list = (List) qr.query(sql, new MapListHandler());
        for(Map<String,Object> map :list){
            for(Map.Entry<String, Object> me : map.entrySet()){
                System.out.println(me.getKey() + "=" + me.getValue());
            }
        }
    }
    
    //將一個(gè)結(jié)果集的列放到一個(gè)對(duì)象中去
    @Test
    public void testScalarHandler() throws SQLException{
        QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
        String sql = "select count(*) from user";  //[13]  list[13]
        /*long l = (Long) qr.query(sql, new ScalarHandler(1));
        int count = (int) l;*///轉(zhuǎn)換方法一
        
        //int count = Integer.parseInt(qr.query(sql, new ScalarHandler(1)).toString());
        //拋出類型轉(zhuǎn)換異常
        
        int count = ((Long)qr.query(sql, new ScalarHandler(1))).intValue();//轉(zhuǎn)換方法二
        System.out.println(count);
    }
    
}

說(shuō)明:

  • 1.對(duì)于有些比較容易理解的方法這里不做過(guò)多的說(shuō)明,相關(guān)說(shuō)明在程序中已經(jīng)注釋了。

  • 2.對(duì)于KeyedHandler方法,首先將一行數(shù)據(jù)分別存入到一個(gè)小Map中,這個(gè)小Map中有{id:1}{name:aaa}這樣的Map數(shù)據(jù),依次類推,然后將這些小Map放在一個(gè)大Map中去,而這個(gè)大Map中的key我們自己可以指定,上面指定的是id。

  • 3.對(duì)于方法MapHandler就很好理解了,就是上面所說(shuō)的將數(shù)據(jù)放到一個(gè)一個(gè)的小Map中。列名就是key。

  • 4.對(duì)于方法MapListHandler,其實(shí)和方法KeyedHandler類似,KeyedHandler是將小Map放在一個(gè)大Map中,而MapListHandler是將小Map放到一個(gè)List中去。

  • 5.對(duì)于方法ScalarHandler,是將一個(gè)結(jié)果集的列放到一個(gè)對(duì)象中去。一般用來(lái)查詢總記錄數(shù)。注意這里容易拋出類型轉(zhuǎn)換異常,需要進(jìn)行處理。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • JDBC概述 在Java中,數(shù)據(jù)庫(kù)存取技術(shù)可分為如下幾類:JDBC直接訪問(wèn)數(shù)據(jù)庫(kù)、JDO技術(shù)、第三方O/R工具,如...
    usopp閱讀 3,642評(píng)論 3 75
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,811評(píng)論 18 399
  • 本文包括:1、DBUtils簡(jiǎn)介2、DbUtils類3、QueryRunner類4、ResultSetHandle...
    廖少少閱讀 21,000評(píng)論 1 24
  • 蔡 勉 旃 堅(jiān) 還 亡 友 財(cái) 徐 珂 蔡璘,字勉旃,吳縣人。重諾責(zé),敦風(fēng)義...
    小胡旭小可耐閱讀 677評(píng)論 0 0
  • 1.最近剛剛看完一本書,叫做《精養(yǎng)父母》。其中有一句話印象深刻:一個(gè)國(guó)家民眾的素質(zhì)可以體現(xiàn)在兩點(diǎn),一是讀書的人數(shù),...
    Willingheart閱讀 250評(píng)論 0 1

友情鏈接更多精彩內(nèi)容