commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,对传统操作数据库的类进行二次封装,可以把结果集转化成List。
先介绍一下数据库的元数据
Connection.getDatabaseMetaData()获得代表DatabaseMetaData元数据的DatabaseMetaData对象。
DataBaseMetaData对象的常用方法:
getURL():返回一个String类对象,代表数据库的URL。
getUserName():返回连接当前数据库管理系统的用户名。
getDatabaseProductName():返回数据库的产品名称。
getDatabaseProductVersion():返回数据库的版本号。
getDriverName():返回驱动驱动程序的名称。
getDriverVersion():返回驱动程序的版本号。
isReadOnly():返回一个boolean值,指示数据库是否只允许读操作。
/** * 此类用于联系数据库得元数据获取 * * */
Connection conn = null;
try{
conn = JDBCUnti.getConnection();
DatabaseMetaData dmd = conn.getMetaData();
System.out.println("数据库得版本:"+dmd.getDatabaseMajorVersion());
System.out.println("数据库名字:"+dmd.getDatabaseProductName());
System.out.println("获取此数据库是否支持给定事务隔离级别"+
dmd.supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED));
}catch(SQLException e){
e.printStackTrace();
}finally{
JDBCUnti.free(null, conn);
}
PreparedStatement.getParameterMetaData() 获得代表PreparedStatement元数据的ParameterMetaData对象。
Select * from user where name=? And password=?
ParameterMetaData对象的常用方法:
getParameterCount(): 获得指定参数的个数
getParameterType(int param):获得指定参数的sql类型,MySQL数据库驱动不支持
ResultSet. getMetaData() 获得代表ResultSet对象元数据的ResultSetMetaData对象。
ResultSetMetaData对象的常用方法:
getColumnCount() 返回resultset对象的列数
getColumnName(int column) 获得指定列的名称
getColumnTypeName(int column)获得指定列的类型
在编写jdbc框架时我们就要用到它
mysqlurl=jdbc:mysql://localhost:3306/lgh?user=root&password=mysql
mysqlclassname=com.mysql.jdbc.Driver
package com.mydbutil.util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import com.mydbutil.dao.ResultSetHandler;
/** * @author lgh * 工具类负责获取数据库连接,释放资源,执行SQL的update和query操 作 * */
public class JdbcUtils {
private static String url = null;
private static String user = null;
private static String password = null;
private static String className = null;
private static String mysqlUrl = null;
//private static Properties into = new Properties();
private static Properties properties = new Properties();
static {
try {
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
properties.load(is);
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
//className = properties.getProperty("className");
className = properties.getProperty("mysqlclassname");
mysqlUrl = properties.getProperty("mysqlurl");
} catch (Exception e) {
e.printStackTrace();
}
}
static{
try {
Class.forName(className); //注册驱动;
} catch (Exception e) {
// TODO: handle exception
}
}
public static Connection getConnection() throws SQLException{
//return DriverManager.getConnection(url,user,password); //获取连接
return DriverManager.getConnection(mysqlUrl); //获取连接
}
//关闭连接
public static void free(Connection connection ,Statement stmt ){
if(stmt!=null){
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void free(ResultSet res, Statement stmt, Connection connection) {
if (res != null) {
try {
res.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
free(connection, stmt);
}
/* * 万能更新 * sql 数据库语句 * Object[] 存放要更新的列数据 * */
public static int update(String sql,Object[] obj) throws SQLException{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
for(int i =0;i<obj.length;i++){
pstmt.setObject(i+1, obj[i]);
}
int i = pstmt.executeUpdate();
return i;
} finally {
JdbcUtils.free(conn, pstmt);
}
}
public static Object query(String sql ,ResultSetHandler rsh,Object... obj) throws SQLException{
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
pstmt = conn.prepareStatement(sql);
for(int i =0;i<obj.length;i++){
pstmt.setObject(i+1, obj[i]);
}
rs = pstmt.executeQuery();
/** * 对于查询返回的结果集处理使用到了策略模式, * 在设计query方法时,query方法事先是无法知道用户对返回的查询结果集如何进行处理的,即不知道结果集的处理策略, * 那么这个结果集的处理策略就让用户自己提供,query方法内部就调用用户提交的结果集处理策略进行处理 * 为了能够让用户提供结果集的处理策略,需要对用户暴露出一个结果集处理接口ResultSetHandler * 用户只要实现了ResultSetHandler接口,那么query方法内部就知道用户要如何处理结果集了 */
return rsh.handler(rs);
} finally {
JdbcUtils.free(conn, pstmt);
}
}
}
对于查询返回的结果集处理使用到了策略模式,在设计query方法时,query方法事先是无法知道用户对返回的查询结果集如何进行处理的,即不知道结果集的处理策略,那么这个结果集的处理策略就让用户自己提供,query方法内部就调用用户提交的结果集处理策略进行处理为了能够让用户提供结果集的处理策略,需要对用户暴露出一个结果集处理接口ResultSetHandler用户只要实现了ResultSetHandler接口,那么query方法内部就知道用户要如何处理结果集了
package com.mydbutil.dao;
import java.sql.ResultSet;
/** * @author lgh * * */
public interface ResultSetHandler {
/** * @Method: handler * @Description: 结果集处理方法 *@author lgh * @param rs 查询结果集 * @return */
public Object handler(ResultSet rs);
}
Field[] fields = bean.getClass().getDeclaredFields();
for (Field f : fields) {
String fName = f.getName();
if (fName.equalsIgnoreCase(columnName)) {
f.setAccessible(true);
f.set(bean, columnData);
}
}
package com.mydbutil.dao.impl;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import com.mydbutil.dao.ResultSetHandler;
public class BeanHandler implements ResultSetHandler {
private Class<?> clazz;
public BeanHandler(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
try {
if (!rs.next()) {
return null;
}
Object bean = clazz.newInstance();
ResultSetMetaData rsmd = rs.getMetaData(); // 得到结果集元数据
int count = rsmd.getColumnCount();
for (int i = 0; i < count; i++) {
String columnName = rsmd.getColumnName(i + 1);
// 得到每列每行的值
// 注意 从数据库中返回的列名 全都是大写的
Object columnData = rs.getObject(i + 1);
// 得到列名所对应的实体类的属性名
// Field field = bean.getClass().getDeclaredField(columnName);
Field[] fields = bean.getClass().getDeclaredFields();
for (Field f : fields) {
String fName = f.getName();
if (fName.equalsIgnoreCase(columnName)) {
f.setAccessible(true);
f.set(bean, columnData);
}
}
}
return bean;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
BeanListHandler 返回一个集合
package com.mydbutil.dao.impl;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.List;
import com.mydbutil.dao.ResultSetHandler;
public class BeanListHandler implements ResultSetHandler {
private Class<?> clazz;
public BeanListHandler(Class<?> clazz) {
this.clazz = clazz;
}
@Override
public Object handler(ResultSet rs) {
try {
List<Object> list = new ArrayList<>();
while (rs.next()) {
Object bean = clazz.newInstance();
//查询结果集的元数据 可以查询结果集的列信息
ResultSetMetaData rsmd = rs.getMetaData();
int count = rsmd.getColumnCount();
for (int i = 0; i < count; i++) {
String columnName = rsmd.getColumnName(i + 1);
Object columnData = rs.getObject(i + 1);
//注意:数据库中返回的列名都是大写的,而我们javabean 中变量并不是大写的
// System.out.println(columnName);
// Field field =
// bean.getClass().getDeclaredField(columnName);
/** * 这地方可以使用map<Object,Object>集合来存放每一行的数据 列名为键 * 然后把map放到list中返回 * 这样就不必构建一个javabean 了 * */
Field[] fields = bean.getClass().getDeclaredFields();
for (Field f : fields) {
String fName = f.getName();
if (fName.equalsIgnoreCase(columnName)) {
f.setAccessible(true);
f.set(bean, columnData);
}
}
}
list.add(bean);
}
return list.size() > 0 ? list : null;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
ScalarHandler.java 返回某一个字段的值
package com.mydbutil.dao.impl;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import com.mydbutil.dao.ResultSetHandler;
/** * @author lgh * ScalarHandler * @Description: 返回某一个字段的值 * */
public class ScalarHandler implements ResultSetHandler {
private Class<?> clazz;
public ScalarHandler(Class<?> clazz){
this.clazz = clazz;
}
public ScalarHandler(){
}
/** * rs 数据库查询的结果集 * return 返回某一个字段的值:例如返回某一条记录的 customerName, 或返回数据表中有多少条记录等. * */
public Object handler(ResultSet rs) {
try{
if (rs.next()) {
return rs.getObject(1);
}
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
package com.mydbutil.demo.test;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.junit.Test;
import com.mydbutil.dao.impl.BeanHandler;
import com.mydbutil.dao.impl.BeanListHandler;
import com.mydbutil.dao.impl.ScalarHandler;
import com.mydbutil.domain.User;
import com.mydbutil.domain.login;
import com.mydbutil.util.JdbcUtils;
import junit.framework.TestCase;
public class TestJdbcs extends TestCase {
@Test
public void testInsert() {
String sql = "insert into t_user values(null,?,?,?,?)";
// Date date = "1980-07-23"
String strDate = "1980-07-23";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");
Date birdate = null;
try {
birdate = sdf.parse(strDate);
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Object[] obj = new Object[] { "LIMING", "123456", "15", new java.sql.Date(birdate.getTime()) };
int i = 0;
try {
i = JdbcUtils.update(sql, obj);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(i);
}
public void testUpdate() throws SQLException {
String sql = "update t_user set name= ? where id=?";
Object[] obj = new Object[] { "灵敏", 86 };
int i = JdbcUtils.update(sql, obj);
System.out.println(i);
}
@Test
public void testQuery() {
// String sql = "select * from login where name = ?";
String sql = "select * from t_user where id = ?";
Object[] obj = new Object[] { 86 };
//login lo = new login();
User user = new User();
User u;
try {
u = (User) JdbcUtils.query(sql, new BeanHandler(user.getClass()), obj);
System.out.println(u);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
public void testQueryAll() throws SQLException {
String sql = "select * from t_user";
//User use = new User();
List<User> users = null;
users = (List<User>) JdbcUtils.query(sql, new BeanListHandler(User.class));
for (User user : users) {
System.out.println(user);
}
}
public void testScalarHandler() throws SQLException{
String sql ="select count(id) from t_user where name=?";
Object[] obj = new Object[] {"jan"};
Number num = (Number) JdbcUtils.query(sql, new ScalarHandler(), obj);
System.out.println(num);
}
}
编写的这个JDBC框架就是模拟Apache的DBUtils框架的实现