一、簡(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.SQLExceptionDbUtils類提供了三個(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ì)自行處理PreparedStatement和ResultSet的創(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)行處理。