博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用反射和ResultSetMetaData实现DBUtils的基本功能
阅读量:5323 次
发布时间:2019-06-14

本文共 4483 字,大约阅读时间需要 14 分钟。

  DBUtils大大简化了JDBC的书写,极大的提高了开发效率,和数据库连接池一起,简化了JDBC开发的流程.简易的自定义数据库连接池可以通过装饰者设计模式和动态代理模式得到很简单的实现,那么DBUtils应该怎么实现呢?为了了解DBUtils其内部工作的流程,我实现了一个自己的DBUtils工具类,实现一些简单的更新和查询操作.  

  ResultSetMetaData是可以获取ResultSet对象的列类型和属性信息的对象.这个类里面有很多方法,在这个案例中,只用到两个:getColumnCount():获取ResultSet结果集中列的数目.getColumnName(int column):根据指定的列数目获取列名.有了这两个方法就可以自己动手去实现一个简易版的DBUtils啦~下面是我实现的步骤:

  1.编写MyQueryRunner的executeUpdate方法.

  这个方法的编写非常简单,因为可以通过dataSource获取Connection,在方法的内部就是简单的jdbc操作.需要注意的是,需要手动设置传入的参数到PreparedStatement中.代码如下:

public int update(String sql, Object... params) {        Connection connection=null;        PreparedStatement preparedStatement=null;        try {            connection=dataSource.getConnection();            preparedStatement=connection.prepareStatement(sql);            for(int i=0;i

  2.编写MyQueryRunner的executeQuery方法.

  这个方法的实现也不难,因为我们将重要的代码交给传入的ResultSetHandler实现对象来处理.代码如下:

//查询会比较麻烦.    //作出三个实现BeanHandler BeanListHandler MapListHandler     public 
T query(String sql, ResultSetHandler
rsh, Object... params) { Connection connection=null; PreparedStatement preparedStatement=null; ResultSet rs=null; try { connection=dataSource.getConnection(); preparedStatement=connection.prepareStatement(sql); if(params!=null) { for(int i=0;i

  3.3个处理器的编写.

  在MyQueryRunner实现自定义查询的实现中,我实现了三个处理器,它们分别是采用了BeanHandler,BeanListHandler,MapListHandler的实现思想,并且给出了最简单易懂(实际上是因为我水平不够= =)的实现.下面说说BeanHandler的实现流程,Handler的实现基本上都是一样的,无非是采用反射获得元素对象,并且将数据封装进去.

  BeanHandler中有两个成员变量,一个T t用来作为要返回的JavaBean,声明在外面供之后封装数据使用,一个Class type对象,用来获取Class,创建JavaBean对象赋值给t,创建Field对象为t的成员变量赋值.在方法的实现中,先通过getColumnCount方法来获取列的数目,遍历每一列,通过getColumnName(int columnCount)方法获取列名,用Class对象的getField方法获取Field对象(这里JavaBean的取值一定要和数据库中相同!否则会报错),再利用Field对象的set方法赋值.当然Field对象对应的成员变量一定是私有的(JavaBean的特性.)因此需要先调用setAccessable方法才可以.具体的代码如下:

public class MyBeanHandler
implements ResultSetHandler{ private Class
type; T t;//需要封装的JavaBean public MyBeanHandler(Class
type) { this.type=type; } @Override public Object handle(ResultSet rs) throws SQLException { try { t=type.newInstance(); ResultSetMetaData metaData = rs.getMetaData(); int count=metaData.getColumnCount();//获取ResultSet中数据的列数 rs.next();//移动指针 //遍历获的每一列的列名,采用反射机制设置值 for(int i=1;i<=count;i++) { String name=metaData.getColumnName(i); Object obj=rs.getObject(i); Field field = type.getDeclaredField(name); field.setAccessible(true); field.set(t, obj);//封装数据进入JavaBean } } catch (Exception e) { e.printStackTrace(); } return t; }}

  MyBeanListHandler的实现步骤,基本和BeanHandler一致.唯一的区别就是采用结果集的next方法遍历每一条记录,而将对象的创建移动到了循环里,这里考虑返回的List对象的增删应该比较少因此采用的是ArrayList.具体实现如下:

public class MyBeanListHandler
implements ResultSetHandler
>{ private Class
type; List
list=new ArrayList
();//可能获取比较多.因此采用ArrayList public MyBeanListHandler(Class
type) { this.type = type; } @Override public List
handle(ResultSet rs) throws SQLException { try { ResultSetMetaData metaData = rs.getMetaData(); int count=metaData.getColumnCount(); while(rs.next()) { T t=type.newInstance(); for(int i=1;i<=count;i++) { String name=metaData.getColumnName(i);//该方法获取列名.获取一系列字段名称.例如name,age... Object obj=rs.getObject(i);//获取字段值 Field field = type.getDeclaredField(name);//获取field对象 field.setAccessible(true); field.set(t, obj);//设置值 } list.add(t); } return list; } catch (Exception e) { throw new RuntimeException(e); } }}

  MapList看上去似乎最复杂,但是实际上实现起来却由于没有采用泛型和反射,是最方便的,代码如下:

public class MyMapListHandler implements ResultSetHandler
>> { private List
> data=new ArrayList<>(); @Override public List
> handle(ResultSet rs) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); int count=metaData.getColumnCount(); while(rs.next()) { Map
map=new HashMap<>(); for(int i=1;i<=count;i++) { Object value=rs.getObject(i); String name=metaData.getColumnName(i); map.put(name, value); } data.add(map); } return data; }}

 

转载于:https://www.cnblogs.com/hlhdidi/p/6014483.html

你可能感兴趣的文章
python tkinter GUI绘制,以及点击更新显示图片
查看>>
Spring面试题
查看>>
C语言栈的实现
查看>>
SRM 628 DIV2
查看>>
2018-2019-2 20165314『网络对抗技术』Exp5:MSF基础应用
查看>>
SecureCRT的使用方法和技巧(详细使用教程)
查看>>
自建数据源(RSO2)、及数据源增强
查看>>
2018icpc徐州OnlineA Hard to prepare
查看>>
使用命令创建数据库和表
查看>>
【转】redo与undo
查看>>
安卓当中的线程和每秒刷一次
查看>>
wpf样式绑定 行为绑定 事件关联 路由事件实例
查看>>
TCL:表格(xls)中写入数据
查看>>
Oracle事务
查看>>
String类中的equals方法总结(转载)
查看>>
标识符
查看>>
一步步教你轻松学奇异值分解SVD降维算法
查看>>
内存地址对齐
查看>>
创新课程管理系统数据库设计心得
查看>>
Could not resolve view with name '***' in servlet with name 'dispatcher'
查看>>