一、简介
- 对象关系映射
- 常用映射工具
- Hibernate用的较多
- Ibatis用的不多
- Commons DbUtils(只是对JDBC简单封装)
二、Apache-DBUtils框架
2.1 简介
commons-dbutils是apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,能极大简化JDBC编码的工作量,同时也不会影响程序的性能。因此此工具称为很多不喜欢Hibernate公司的首选。
2.2 工具类(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
。
2.3 工具类(QueryRunner类)
- 该类简单化了sql查询,它与
ResultSetHandler
组合在一起使用可以完成大部分的数据库操作,能够大大的减少编码量。 - QueryRunner类提供了两个构造方法:
默认的构造方法和需要一个javax.sql.DataSource
来作参数的构造方法。 - 主要方法:
-
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.4 ResultSetHandler接口
- 该接口用于处理
java.sql.ResultSet
,将数据按要求换行为另一种形式。 - 提供了一个单独的方法
Object handle (java.sql.ResultSet .rs)
- 此接口的实现类
-
ArrayHandler
把结果集中的第一行数据转成对象数组。 -
ArrayListHandler
把结果集中的每一行数据都转成一个数组,再存放到List中。 -
BeanHandler
将结果集中的第一行数据封装到一个对应的JavaBean实例中。 -
BeanListHandler
将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。 -
ColumnListHandler
将结果集中某一列的数据存放到List中。 -
KeyedHandler(name)
将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。大map的key是自己指定,小map的key是列名。 -
MapHandler
将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。 -
MapListHandler
将结果集中的每一行数据都封装到一个Map里,然后再存放到List
-
以下所有示例都在工程(day17
)
2.5示例一:使用此框架完成基本的增删改查和批处理操作
首先建立数据库:
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完成大数据(不建议用)
/***************************************************************
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
//替换参数
/*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);
}
}
说明:
- 1.对于基本的增删改查,其使用方式基本一样。我们只需要将相关的sql和参数传递进去即可使用QueryRunner类帮我们实现这几个基本操作。而对于查找来说,也是需要使用相关的处理类,如上面使用到的BeanHandler和BeanListHandler类来进行处理,这和我们之前自己编写框架的思路是一样的。
- 2.对于大数据,我们不建议使用此框架处理。
2.6实例二:测试此框架的处理器
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 {
//测试dbutils各种类型的处理器
//把结果集中的第一行数据转成对象数组
@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)); //打印出第一行数据
}
//把结果集中的每一行数据都转成一个数组,再存放到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中的所有对象数据
}
}
//将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到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
}
//将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个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("----------------");
}
}
//将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
@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());
}
}
//将结果集中的每一行数据都封装到一个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());
}
}
}
//将一个结果集的列放到一个对象中去
@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;*///转换方法一
//int count = Integer.parseInt(qr.query(sql, new ScalarHandler(1)).toString());
//抛出类型转换异常
int count = ((Long)qr.query(sql, new ScalarHandler(1))).intValue();//转换方法二
System.out.println(count);
}
}
说明:
1.对于有些比较容易理解的方法这里不做过多的说明,相关说明在程序中已经注释了。
2.对于KeyedHandler方法,首先将一行数据分别存入到一个小Map中,这个小Map中有
{id:1}
、{name:aaa}
这样的Map数据,依次类推,然后将这些小Map放在一个大Map中去,而这个大Map中的key我们自己可以指定,上面指定的是id。3.对于方法MapHandler就很好理解了,就是上面所说的将数据放到一个一个的小Map中。列名就是key。
4.对于方法MapListHandler,其实和方法KeyedHandler类似,KeyedHandler是将小Map放在一个大Map中,而MapListHandler是将小Map放到一个List中去。
5.对于方法ScalarHandler,是将一个结果集的列放到一个对象中去。一般用来查询总记录数。注意这里容易抛出类型转换异常,需要进行处理。