1. 程式人生 > >Java中JDBC的常見封裝

Java中JDBC的常見封裝

ThreadLocal

ThreadLocal API

ThreadLocal類只有三個方法:

l  void set(T value):儲存值;

l  T get():獲取值;

l  void remove():移除值。

key

value

thread1

aaa

thread2

bbb

thread3

ccc

ThreadLocal的內部是Map

ThreadLocal內部其實是個Map來儲存資料。雖然在使用ThreadLocal時只給出了值,沒有給出鍵,其實它內部使用了當前執行緒做為鍵。

class MyThreadLocal<T> {

    private

Map<Thread,T> map = new HashMap<Thread,T>();

    public void set(T value) {

       map.put(Thread.currentThread(), value);

    }

    public void remove() {

       map.remove(Thread.currentThread());

    }

    public T get() {

       return map.get(Thread.currentThread());

    }

}

BaseServlet

BaseServlet的作用

在開始客戶管理系統之前,我們先寫一個工具類:BaseServlet。

我們知道,寫一個專案可能會出現N多個Servlet,而且一般一個Servlet只有一個方法(doGet或doPost),如果專案大一些,那麼Servlet的數量就會很多。

寫一個BaseServlet。它的作用是讓一個Servlet可以處理多種不同的請求。不同的請求呼叫Servlet的不同方法。我們寫好了BaseServlet後,讓其他Servlet繼承BaseServlet,例如CustomerServlet繼承BaseServlet,然後在CustomerServlet中提供add()、update()、delete()等方法,每個方法對應不同的請求。

BaseServlet分析

我們知道,Servlet中處理請求的方法是service()方法,這說明我們需要讓service()方法去呼叫其他方法。例如呼叫add()、mod()、del()、all()等方法!具體呼叫哪個方法需要在請求中給出方法名稱!然後service()方法通過方法名稱來呼叫指定的方法。

無論是點選超連結,還是提交表單,請求中必須要有method引數,這個引數的值就是要請求的方法名稱,這樣BaseServlet的service()才能通過方法名稱來呼叫目標方法。例如某個連結如下:

<a href=”/xxx/CustomerServlet?method=add”>新增客戶</a>

BaseServlet程式碼

public class BaseServlet extends HttpServlet {

    /*

     * 它會根據請求中的m,來決定呼叫本類的哪個方法

     */

    protected void service(HttpServletRequest req, HttpServletResponse res)

           throws ServletException, IOException {

       req.setCharacterEncoding("UTF-8");

       res.setContentType("text/html;charset=utf-8");

       // 例如:http://localhost:8080/demo1/xxx?method=add

       String methodName = req.getParameter("method");// 它是一個方法名稱

       // 當沒用指定要呼叫的方法時,那麼預設請求的是execute()方法。

       if(methodName == null || methodName.isEmpty()) {

           methodName = "execute";

       }

       Class c = this.getClass();

       try {

           // 通過方法名稱獲取方法的反射物件

           Method m = c.getMethod(methodName, HttpServletRequest.class,

                  HttpServletResponse.class);

           // 反射方法目標方法,也就是說,如果methodNameadd,那麼就呼叫add方法。

           String result = (String) m.invoke(this, req, res);

           // 通過返回值完成請求轉發

           if(result != null && !result.isEmpty()) {

              req.getRequestDispatcher(result).forward(req, res);

           }

       } catch (Exception e) {

           throw new ServletException(e);

       }

    }

}

DBUtils

DBUtils簡介

DBUtils是Apache Commons元件中的一員,開源免費!

DBUtils是對JDBC的簡單封裝,但是它還是被很多公司使用!

DBUtils的Jar包:dbutils.jar

DBUtils主要類

l  DbUtils:都是靜態方法,一系列的close()方法;

l  QueryRunner:

Ø  update():執行insert、update、delete;

Ø  query():執行select語句;

Ø  batch():執行批處理。

QueryRunner之更新

QueryRunner的update()方法可以用來執行insert、update、delete語句。

1.       建立QueryRunner

構造器:QueryRunner();

2.       update()方法

intupdate(Connection con, String sql, Object… params)

    @Test

    public void fun1() throws SQLException {

       QueryRunner qr = new QueryRunner();

       String sql = "insert into user values(?,?,?)";

       qr.update(JdbcUtils.getConnection(), sql, "u1", "zhangSan", "123");

    }

  還有另一種方式來使用QueryRunner

1.       建立QueryRunner

構造器:QueryRunner(DataSource)

2.       update()方法

intupdate(String sql, Object… params)

這種方式在建立QueryRunner時傳遞了連線池物件,那麼在呼叫update()方法時就不用再傳遞Connection了。

    @Test

    public void fun2() throws SQLException {

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

       String sql = "insert into user values(?,?,?)";

       qr.update(sql, "u1", "zhangSan", "123");

    }

ResultSetHandler

執行select語句之後得到的是ResultSet,然後我們還需要對ResultSet進行轉換,得到最終我們想要的資料。你可以希望把ResultSet的資料放到一個List中,也可能想把資料放到一個Map中,或是一個Bean中。

DBUtils提供了一個介面ResultSetHandler,它就是用來ResultSet轉換成目標型別的工具。你可以自己去實現這個介面,把ResultSet轉換成你想要的型別。

DBUtils提供了很多個ResultSetHandler介面的實現,這些實現已經基本夠用了,我們通常不用自己去實現ResultSet介面。

l  MapHandler:單行處理器!把結果集轉換成Map<String,Object>,其中列名為鍵!

l  MapListHandler:多行處理器!把結果集轉換成List<Map<String,Object>>;

l  BeanHandler:單行處理器!把結果集轉換成Bean,該處理器需要Class引數,即Bean的型別;

l  BeanListHandler:多行處理器!把結果集轉換成List<Bean>;

l  ColumnListHandler:多行單列處理器!把結果集轉換成List<Object>,使用ColumnListHandler時需要指定某一列的名稱或編號,例如:new ColumListHandler(“name”)表示把name列的資料放到List中。

l  ScalarHandler:單行單列處理器!把結果集轉換成Object。一般用於聚集查詢,例如select count(*) from tab_student。

QueryRunner之查詢

QueryRunner的查詢方法是:

public<T> T query(String sql, ResultSetHandler<T> rh, Object… params)

public<T> T query(Connection con, String sql, ResultSetHandler<T> rh,Object… params)

query()方法會通過sql語句和params查詢出ResultSet,然後通過rh把ResultSet轉換成對應的型別再返回。

    @Test

    public void fun1() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select * from tab_student where number=?";

       Map<String,Object> map = qr.query(sql, new MapHandler(), "d_2000");

       System.out.println(map);

    }

    @Test

    public void fun2() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select * from tab_student";

       List<Map<String,Object>> list = qr.query(sql, new MapListHandler());

       for(Map<String,Object> map : list) {

           System.out.println(map);

       }

    }

    @Test

    public void fun3() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select * from tab_student where number=?";

       Student stu = qr.query(sql, new BeanHandler<Student>(Student.class), "d_2000");

       System.out.println(stu);

    }

    @Test

    public void fun4() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select * from tab_student";

       List<Student> list = qr.query(sql, new BeanListHandler<Student>(Student.class));

       for(Student stu : list) {

           System.out.println(stu);

       }

    }

    @Test

    public void fun5() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select * from tab_student";

       List<Object> list = qr.query(sql, new ColumnListHandler("name"));

       for(Object s : list) {

           System.out.println(s);

       }

    }

    @Test

    public void fun6() throws SQLException {

       DataSource ds = JdbcUtils.getDataSource();

       QueryRunner qr = new QueryRunner(ds);

       String sql = "select count(*) from tab_student";

       Number number = (Number)qr.query(sql, new ScalarHandler());

       int cnt = number.intValue();

       System.out.println(cnt);

    }

QueryRunner之批處理

QueryRunner還提供了批處理方法:batch()。

我們更新一行記錄時需要指定一個Object[]為引數,如果是批處理,那麼就要指定Object[][]為引數了。即多個Object[]就是Object[][]了,其中每個Object[]對應一行記錄:

@Test

public void fun() throws SQLException {

    DataSource ds = JdbcUtils.getDataSource();

    QueryRunner qr = new QueryRunner(ds);

    String sql = "insert into tab_student values(?,?,?,?)";

    Object[][] params = new Object[10][];//表示要插入10行記錄

    for(int i = 0; i < params.length; i++) {

       params[i] = new Object[]{"d_300" + i, "name" + i, 30 + i, i%2==0?"":""};

    }

    qr.batch(sql, params);

}