天天看點

Apache的DBUtils使用詳解

一、commons-dbutils簡介 

  commons-dbutils 是 Apache 組織提供的一個開源 JDBC工具類庫,它是對JDBC的簡單封裝,學習成本極低,并且使用dbutils能極大簡化jdbc編碼的工作量,同時也不會影響程式的性能。

  1. org.apache.commons.dbutils (該包中的類主要幫助我們更便捷的操作JDBC)
  2. org.apache.commons.dbutils.handlers(該包中的類都是實作org.apache.commons.dbutils.ResultSetHandler接口的實作類)
  3. org.apache.commons.dbutils.wrappers(該包中的類主要是封裝了對Sql結果集的操作)

二、QueryRunner類使用講解

  該類簡單化了SQL查詢,它與ResultSetHandler組合在一起使用可以完成大部分的資料庫操作,能夠大大減少編碼量。

  QueryRunner類提供了兩個構造方法:

  • 預設的構造方法
  • 需要一個 javax.sql.DataSource 來作參數的構造方法。

2.1、QueryRunner類的主要方法

  public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:執行一個查詢操作,在這個查詢中,對象數組中的每個元素值被用來作為查詢語句的置換參數。該方法會自行處理 PreparedStatement 和 ResultSet 的建立和關閉。

  public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException: 幾乎與第一種方法一樣;唯一的不同在于它不将資料庫連接配接提供給方法,并且它是從提供給構造方法的資料源(DataSource) 或使用的setDataSource 方法中重新獲得 Connection。

  public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 執行一個不需要置換參數的查詢操作。

  public int update(Connection conn, String sql, Object[] params) throws SQLException:用來執行一個更新(插入、更新或删除)操作。

  public int update(Connection conn, String sql) throws SQLException:用來執行一個不需要置換參數的更新操作。

2.2、使用QueryRunner類實作CRUD(增删查改)

以下使用SQLServer2008版資料庫
package org.apache.commons.dbutils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;

import javax.sql.DataSource;

import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;



/**
 * 使用QueryRunner 類實作CRUD(create,read,update,delete)
 * @author Administrator
 *
 */
public class QueryRunnerTest {

	/*
	 測試表
	 create table stuInfo
	(
		stuNo int primary key identity (1,1),--學号
		stuName nvarchar(10) not null,--學生姓名
		stuSex nvarchar(2) not null,--學生性别
		stuAge int not null,--學生年齡
		stuSeat int not null,--學生座位
		stuAddress nvarchar(20) --學生住址
		
	)*/
	
	public static void main(String[] args) {
		QueryRunnerTest test = new QueryRunnerTest();
		test.add();
		test.delete();
		test.update();
		test.find();
		test.getAll();

	}
	
	private static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;Database=student", "sa", "sasa");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(conn);
		return conn;
		
	}
	
	//添加方法
	public void add () {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "insert into stuInfo (stuName,stuSex,stuAge,stuSeat,stuAddress) values (?,?,?,?,?)";
		Object param[] = {"張良","男",20,11,"南韓"};
		int i;
		try {
			i = qr.update(conn, sql, param);
			System.out.println("添加成功:"+i);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//删除方法
	public void delete() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql ="delete from stuInfo where stuNo=?";
		try {
			int i = qr.update(conn, sql, 7);
			System.out.println("删除成功:"+i);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//修改方法
	public void update() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "update stuInfo set stuName=? where stuNo=?";
		Object params[] = {"胡歌",3};
		try {
			int i = qr.update(conn, sql, params);
			System.out.println("修改成功:"+i);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//查詢方法
	public void find() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo where stuNo=?";
		Object params[] = {5};
		try {
			StuInfo stuInfo = (StuInfo)qr.query(conn, sql, new BeanHandler<StuInfo>(StuInfo.class), params);
			System.out.println("查詢成功:"+stuInfo);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//查詢所有
	public void getAll() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql ="select * from stuInfo";
		ArrayList<StuInfo> list;
		try {
			list = (ArrayList<StuInfo>) qr.query(conn, sql, new BeanListHandler<StuInfo>(StuInfo.class));
			for (StuInfo stuInfo : list) {
				System.out.println(stuInfo);
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	
	
	
	
	

}
           

三、ResultSetHandler接口使用講解

  該接口用于處理java.sql.ResultSet,将資料按要求轉換為另一種形式。

  ResultSetHandler接口提供了一個單獨的方法:Object handle (java.sql.ResultSet .rs)

3.1、ResultSetHandler接口的實作類

  • ArrayHandler:把結果集中的第一行資料轉成對象數組。
  • ArrayListHandler:把結果集中的每一行資料都轉成一個數組,再存放到List中。
  • BeanHandler:将結果集中的第一行資料封裝到一個對應的JavaBean執行個體中。
  • BeanListHandler:将結果集中的每一行資料都封裝到一個對應的JavaBean執行個體中,存放到List裡。
  • ColumnListHandler:将結果集中某一列的資料存放到List中。
  • KeyedHandler(name):将結果集中的每一行資料都封裝到一個Map裡,再把這些map再存到一個map裡,其key為指定的key。
  • MapHandler:将結果集中的第一行資料封裝到一個Map裡,key是列名,value就是對應的值。
  • MapListHandler:将結果集中的每一行資料都封裝到一個Map裡,然後再存放到List

3.2、測試dbutils各種類型的處理器

JavaBean類
package org.apache.commons.dbutils;

public class StuInfo {
	private String stuName;
	private String stuSex;
	private int stuAge;
	private int stuSeat;
	private String stuAddress;
	
	
	
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public String getStuSex() {
		return stuSex;
	}
	public void setStuSex(String stuSex) {
		this.stuSex = stuSex;
	}
	public int getStuAge() {
		return stuAge;
	}
	public void setStuAge(int stuAge) {
		this.stuAge = stuAge;
	}
	public int getStuSeat() {
		return stuSeat;
	}
	public void setStuSeat(int stuSeat) {
		this.stuSeat = stuSeat;
	}
	public String getStuAddress() {
		return stuAddress;
	}
	public void setStuAddress(String stuAddress) {
		this.stuAddress = stuAddress;
	}
	
	
	//重寫toString方法
	//當需要将一個對象輸出到顯示器時,通常要調用他的toString()方法,将對象的内容轉換為字元串.java中的所有類預設都有一個toString()方法
	//預設情況下 System.out.println(對象名)或者System.out.println(對象名.toString())輸出的是此對象的類名和此對象對應記憶體的首位址如果想自定義輸出資訊必須重寫toString()方法
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return ("姓名:"+stuName+"\n"+"年齡:"+stuAge+";"+"性别:"+stuSex+";"+"座位:"+stuSeat+";"+"位址:"+stuAddress);
	}
	
	
	
	

}
           
各種結果集處理方法
package org.apache.commons.dbutils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.BeanMapHandler;
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;

/**
 * Dbutils結果集執行個體
 * 單行資料處理:ScalarHandler		ArrayHandler		MapHandler		BeanHandler
 * 多行資料處理:BeanListHandler		AbstractkeyedHandler(KeyedHandler	BeanMapHandler)
 * 			 AbstractListHandler(ArrayListHandler	MapListHandler	ColumnListHandler)
 * 可供擴充的類:BaseResultSetHandler
 * @author Administrator
 *
 */
public class ResultSetHandlerTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ResultSetHandlerTest test = new ResultSetHandlerTest();
		//test.testColumnListHandler();
		test.testScalarHandler();
		test.testColumnListHandler();
		test.testArrayHandler();
		test.testArrayListHandler();
		test.testMapHandler();
		test.testMapListHandler();
		test.testKeyedHandler();
		test.testBeanHandler();
		test.testBeanListHandler();
		test.testBeanMapHandler();

	}
	
	private static Connection getConnection() {
		Connection conn = null;
		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;Database=student", "sa", "sasa");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(conn);
		return conn;
		
	}
	
	//ScalarHandler<T>用于擷取結果集中第一行某列的資料并轉換成T表示的實際對象。( 該類對結果集的處理直接在 handle 方法中進行,不涉及 dbutils 庫的其他類)
	public void testScalarHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			//ScalarHandler的參數為空或null時,傳回第一行第一列的資料
			int i = qr.query(conn, sql, new ScalarHandler<Integer>());
			System.out.println("Scalarhandler:"+i);
			
			//ScalarHandler的參數可以是列的索引(從1開始)或是列名
			String name = qr.query(conn, sql, new ScalarHandler<String>(2));
			System.out.println("學生姓名:"+name);
			String stuName = qr.query(conn, sql, new ScalarHandler<String>("stuName"));
			System.out.println("stuName:"+stuName);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//ColumnListHandler<T>:根據列索引或列名擷取結果集中某列的所有資料,并添加到ArrayList中。可以看成ScalarHandler<T>的加強版
		public void testColumnListHandler() {
			Connection conn = getConnection();
			QueryRunner qr = new QueryRunner();
			String sql = "select * from stuInfo";
			try {
				List<String> list = (List) qr.query(conn, sql, new ColumnListHandler<String>("stuName"));
				//List<String> list = (List) qr.query(conn, sql, new ColumnListHandler<String>(2));
				for (String string : list) {
					System.out.println(string);
				}
				System.out.println(list);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
	
	//ArrayHandler:把結果集中的第一行資料轉成對象數組(用于擷取結果集中的第一行資料,并将其封裝到數組中,一列值對應一個數組元素)
	public void testArrayHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		try {
			Object result[] = qr.query(conn, sql, new ArrayHandler());
			System.out.println("ArrayHandler:"+Arrays.asList(result));
			System.out.println("ArrayHandler:"+Arrays.toString(result));
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	//ArrayListHandler:把結果集中的每一行資料都轉成一個Object數組(處理過程等同于ArrayHandler),再将該數組添加到ArrayList中。
	//簡單點,就是将每行資料經ArrayHandler處理後,添加到ArrayListhandler中
	public void testArrayListHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		try {
			List<Object[]> list = (List) qr.query(conn, sql, new ArrayListHandler());
			for (Object[] objects : list) {
				System.out.println(Arrays.asList(objects));
				System.out.println(Arrays.toString((Object[])objects));
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	//KeyedHandler:用于擷取所有結果集,将每行結果集轉換為Map<String,Object>,并指定某列為Key。
	//可以簡單認為是一個雙層Map,相當于先對每行資料執行MapHandler,再為其指定Key添加到HashMap中.
	//KeyedHadler<K>中的<K>是指定的列值得類型
	public void testKeyedHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			//在這裡,指定主鍵stuNo為結果Key
			//注意:也可指定其他列作為Key,如果選取的列值存在重複,則後面的會覆寫前面的,以保證HashMaP中Key值是唯一的 
			Map<Integer,Map> map = (Map)qr.query(conn, sql, new KeyedHandler("stuNo"));
			//Map<Integer,Map> map = (Map)qr.query(conn, sql, new KeyedHandler(1));
			for (Map.Entry<Integer, Map> element : map.entrySet()) {//entrySet()傳回此映射中包含的映射關系的 Set 視圖。
				int stuNo = element.getKey();
				
				Map<String,Object> innermap = element.getValue();
				for (Map.Entry<String, Object> innerelement : innermap.entrySet()) {
					String columnName = innerelement.getKey();
					Object value = innerelement.getValue();
					System.out.println(columnName+"="+value);
					System.out.println("-------------------");
				}
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//MapHandler:将結果集的第一行資料封裝到一個Map裡,Map中key是列名,value就是對應的值
	public void testMapHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			Map<String,Object> map = (Map)qr.query(conn, sql, new MapHandler());
			for (Map.Entry<String, Object> me : map.entrySet()) {
				System.out.println(me.getKey()+"="+me.getValue());
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//MapListHandler:将結果集每行資料轉換為Map(處理結果等同于MapHandler),再将Map添加到ArrayList中
	public void testMapListHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			List<Map> list = (List)qr.query(conn, sql, new MapListHandler());
			for (Map<String,Object> map : list) {
				System.out.println((Map<String,Object>) map);
				/*for (Map.Entry<String, Object> me : map.entrySet()) {
					System.out.println(me.getKey()+"="+me.getValue());
				}*/
			}
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//BeanHandler<T>:将結果集的第一行資料封裝到對應的JavaBean執行個體中
	//注意:資料庫中表中字段要和JavaBean中屬性保持一緻
	public void testBeanHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			StuInfo stuInfo = qr.query(conn, sql, new BeanHandler<StuInfo>(StuInfo.class));
			System.out.println("BeanHandler:"+stuInfo);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//BeanListHandler<T>:用于将結果集的每一行資料轉換為JavaBean,再将這個JavaBean添加到ArrayList中,可以看成BeanHandler的進階版
	public void testBeanListHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			List<StuInfo> list = (List)qr.query(conn, sql, new BeanListHandler<StuInfo>(StuInfo.class));
			System.out.println("BeanListHandler:"+list);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//BeanMapHandler:用于擷取所有結果集,将每行結果集轉換為JavaBean作為value,并指定某列為Key,封裝到HashMap中。
	//相當于,對每行資料做BeanHandler一樣的處理後,再指定列值為key封裝到HashMap中。
	public void testBeanMapHandler() {
		Connection conn = getConnection();
		QueryRunner qr = new QueryRunner();
		String sql = "select * from stuInfo";
		
		try {
			Map<Integer,StuInfo> map = qr.query(conn, sql, new BeanMapHandler<Integer,StuInfo>(StuInfo.class, 1));
			System.out.println("BeanMapHandler:"+map);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
           

四、DbUtils類使用講解

  DbUtils :提供如關閉連接配接、裝載JDBC驅動程式等正常工作的工具類,裡面的所有方法都是靜态的。主要方法如下:

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

  public static void closeQuietly(…): 這一類方法不僅能在Connection、Statement和ResultSet為NULL情況下避免關閉,還能隐藏一些在程式中抛出的SQLEeception。

  public static void commitAndCloseQuietly(Connection conn): 用來送出連接配接,然後關閉連接配接,并且在關閉連接配接時不抛出SQL異常。 

  public static boolean loadDriver(java.lang.String driverClassName):這一方裝載并注冊JDBC驅動程式,如果成功就傳回true。使用該方法,你不需要捕捉這個異常ClassNotFoundException。