模仿dbutils的jdbc框架
来源:互联网 发布:淘宝大学哪家商学院好 编辑:程序博客网 时间:2024/06/05 18:01
- 1、Commonsdbutils是什么?
commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,对传统操作数据库的类进行二次封装,可以把结果集转化成List。
开始之前
先介绍一下数据库的元数据
元数据介绍
1.1 DataBaseMetaData元数据
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); }
1.2ParameterMetaData元数据
PreparedStatement.getParameterMetaData() 获得代表PreparedStatement元数据的ParameterMetaData对象。
Select * from user where name=? And password=?
ParameterMetaData对象的常用方法:
getParameterCount(): 获得指定参数的个数getParameterType(int param):获得指定参数的sql类型,MySQL数据库驱动不支持
1.3ResultSetMetaData元数据
ResultSet. getMetaData() 获得代表ResultSet对象元数据的ResultSetMetaData对象。
ResultSetMetaData对象的常用方法:
getColumnCount() 返回resultset对象的列数getColumnName(int column) 获得指定列的名称getColumnTypeName(int column)获得指定列的类型
在编写jdbc框架时我们就要用到它
使用元数据封装简单的JDBC框架
2.1定义一个JDBCUtils工具类
- c3p0配置文件
mysqlurl=jdbc:mysql://localhost:3306/lgh?user=root&password=mysqlmysqlclassname=com.mysql.jdbc.Driver
- 工具类负责获取数据库连接,释放资源,执行SQL的update和query操 作,代码如下:
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方法内部就知道用户要如何处理结果集了
- ResultSetHandler接口实现代码
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);}
- 具体的实现类,分别处理不同的查询
BeanHandler 返回查询的一行值
注意:注意 从数据库中返回的列名 全都是大写的
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); } }
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; }}
- 测试
TestJdbcs.java
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框架的实现
- 模仿dbutils的jdbc框架
- JDBC框架入门及DBUtils的入门
- DBUtils框架简化JDBC开发
- JDBC框架 和 Apache—DBUtils框架
- DBUtils框架的使用
- 自定义JDBC框架(仿DBUtils)
- jdbc之Apache—DBUtils框架
- 简单JDBC框架——DBUtils
- JDBC元数据和DbUtils框架
- JDBC与DBUtils的区别
- JDBC:Apache DBUtils的使用
- jdbc优化-DButils的使用
- Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用
- Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用
- Java Web(十) JDBC的增删改查,C3P0等连接池,dbutils框架的使用
- 继hibernate后又一ORM框架commons-dbutils的JDBC第一次使用日记
- 传智播客---DBUtils框架的使用
- Apache的DBUtils框架学习
- 动态规划-3016-不能后退的格子
- iOS内存话题: 弱引用下的懒加载
- Make My Ostream!
- 【C语言】实现一个通讯录(三:加入文件读写)
- Apache Zeppelin使用入门指南:添加外部依赖
- 模仿dbutils的jdbc框架
- H3C模拟器---HCL使用心得
- SQLMAP- 自动注入
- SM2算法第二十篇:CRYPTO_set_mem_debug_functions和CRYPTO_mem_ctrl
- Maven学习总结(八)——使用Maven构建多模块项目
- 我的sublime text 3 快捷键配置。
- C++插件化开发,插件化系统
- HDU 4966 GGS-DDU(无固定根最小树形图)
- Bootloader架构设计