使用元数据简化jdbc代码---查询操作(用到反射)

一  思路分析

简化就是把共同的地方提取出来并放到一个方法里,在用到时只要调用就ok了,上一篇介绍了更新的操作,而查询的操作相对来说比较复杂,因为在查询之后不知道输出的列是多少,这是相对于框架的设计者来说的,但是如果相对于程序员是知道有多少列的,所以可以传一个接口,用实现类去给结果集赋值,并返回。

二  代码分析(根据ID获取)

1.提取简化的代码   DBManager.java

//对查询的优化

public static Object find(String sql, Object[] params, ResultSetHandler rsh) throws SQLException {

Connection con = null;

PreparedStatement st = null;

ResultSet rs = null;

try {

con = DBManager_c3p0.getConnection();

st = con.prepareStatement(sql);

for (int i = 0; i < params.length; i++) {

st.setObject(i + 1, params[i]);

}

rs = st.executeQuery();

// 对结果集的处理,不知道有多少行,给他传个方法,

// 即是调用程序员传过来对结果集进行处理 的方法

return rsh.handler(rs);

}  finally {

DBManager.release(con, st, rs);

}

}

注:Object[] params为占位符的数组

ResultSetHandler rsh对结果集的处理器,即上面所说的接口。

2.接口---用来向上一个方法中传的对象    ResultSetHandler.java

import java.sql.ResultSet;

//结果集处理器接口

public interface ResultSetHandler {

public Object handler(ResultSet rs);

}

3. 编写接口的实现类

public class MyResultSetHandler implements ResultSetHandler {

// 编写实现的类

public Object handler(ResultSet rs) {

User user = new User();

try {

if (rs.next()) {

user.setId(rs.getInt(1));

user.setName(rs.getString(2));

user.setPassword(rs.getString(3));

user.setEamil(rs.getString(4));

}

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return user;

}

}

4.使用方法    UserDaoImpl.java

public void find() throws SQLException {

String sql = "select * from users where id=?";

Object[] params = { 5 };

MyResultSetHandler rsh = new MyResultSetHandler();

User user = (User) DBManager.find(sql, params, rsh);

System.out.println(user.toString());

}

5.测试

new UserDaoImpl().find();

三  缺陷思考和解决

1.缺陷

这样虽然可以解决查询的问题,但是只是相对于一个类,一个程序员知道类有多少列,但是如果让开发框架的人来写,他们不知道是什么类,不知道类中有多少列,所以要用到反射的机制来获取类,获取类的属性(数据库中的字段封装成的私有属性),这样实现接口的类又是一次变革。

2.实现接口的类

//作为框架的开发者,构建一个结果集的处理器,将结果集的一行记录封装在一个bean对象中

public class BeanHandler implements ResultSetHandler {

// 传递javabean对象的class对象

public Class clazz;// 一种类型的对象利用反射机制创建指定类型的对象

public BeanHandler(Class clazz) {

this.clazz = clazz;

}

public Object handler(ResultSet rs) {

try {

if (!rs.next()) {

return null;

}

// 读取结果集中的各个类封装到javabean中

// 创建的是javabean对象

Object bean = clazz.newInstance();

// 读取结果集的元数据对象-------得到结果集中有多少列

ResultSetMetaData meta = (ResultSetMetaData) rs.getMetaData();

// 得到一共有几列

int count = meta.getColumnCount();

for (int i = 1; i <= count; i++) {

// 得到第i列的列名

String columnName = meta.getColumnName(i);

// 从结果集中根据列名读取值

Object value = rs.getObject(columnName);

// 通过反射的机制得到javabean里的某一个属性对应的Field对象

Field f = bean.getClass().getDeclaredField(columnName);

f.setAccessible(true);

f.set(bean, value);

}

return bean;

} catch (Exception e) {

// 再次抛出异常,让上一级去处理

throw new RuntimeException(e);

}

}

}

3.用此方法去调用

public void findById() throws SQLException {

// 通过反射的机制去传任意一个javabean对象

String sql = "select * from users where id=?";

Object[] params = { 1 };

BeanHandler rsh = new BeanHandler(User.class);

User user = (User) DBManager.find(sql, params, rsh);

System.out.println(user.toString());

}

四  查询所有---用反射的机制获取并测试

1.查询所有并返回

public class BeanListHandler implements ResultSetHandler {

// 传递javabean对象的class对象

public Class clazz;// 一种类型的对象 利用反射机制创建指定类型的对象.

public BeanListHandler(Class clazz) {

this.clazz = clazz;

}

public Object handler(ResultSet rs) {

try {

List list = new ArrayList();

// 读取一行

while (rs.next()) {

// 封装到bean对象

Object bean = clazz.newInstance();

ResultSetMetaData meta = rs.getMetaData();

int count = meta.getColumnCount();

for (int i = 1; i <= count; i++) {

String columnName = meta.getColumnName(i);

// 通过列的名称读取列的值

Object value = rs.getObject(columnName);

// 得到属性值

Field f = clazz.getDeclaredField(columnName);

// 设置值 是私有的必须先为true,才可访问

f.setAccessible(true);

f.set(bean, value);

}

// 该bean对象加入到list集合

list.add(bean);

}

return list;

} catch (Exception e) {

throw new RuntimeException();

}

}

}

2.使用方法去调用

public List findAll() {

List list = null;

String sql = "select * from users";

Object[] params = {};

BeanListHandler rsh = new BeanListHandler(User.class);

try {

list = (List) DBManager.find(sql, params, rsh);

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return list;

}

3.测试类

public static void main(String[] args) {

UserDaoImpl obj = new UserDaoImpl();

List<User> list = obj.findAll();

System.out.println(list.size());

for(User entity:list){

System.out.println(entity.toString());

}

}

使用元数据简化jdbc代码---查询操作(用到反射)的更多相关文章

  1. [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. Java 使用JDBC连接查询操作数据

    import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.sql. ...

  3. JDBC最原始的代码做查询操作

    首先编写一个User类. public class User { private String username; private String password; public String get ...

  4. 结合java的反射和泛型性质简化JDBC和相应的同步等服务器数据库操作代码

    github地址:https://github.com/hzphzp/HeartTrace_Server 我们的服务器端数据库并没有用sqllite, 而是直接用mysql,并且用JDBC直接进行操作 ...

  5. JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法

    JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...

  6. 使用Spring简化JDBC操作数据库

    Spring的开发初衷是为了减轻企业级开发的复杂度,其对数据库访问的支持亦如此,使用Spring访问数据库能带来以下好处: 1.1     简化代码 使用原生的JDBC访问数据库,一般总是要执行以下步 ...

  7. 【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法

    转自:http://www.cnblogs.com/ysw-go/ JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 ...

  8. MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. 使用Spring JDBCTemplate简化JDBC的操作

    使用Spring JDBCTemplate简化JDBC的操作 接触过JAVA WEB开发的朋友肯定都知道Hibernate框架,虽然不否定它的强大之处,但个人对它一直无感,总感觉不够灵活,太过臃肿了. ...

随机推荐

  1. js实现私有变量

    一.块级作用域 js中没有块级作用域的概念,可用匿名函数实现,由于匿名函数执行完一遍后,内部没有引用其变量对象的函数,其变量对象被清除,后面则引用不到其中的变量 (function(){ //块级作用 ...

  2. redis 数据库迁移

    老大让把 一台机器上 redis 中所有的数据,迁移到另一台机器上 查了一下可以拷贝 rdb 文件, 此方法只适用于迁移到一个新的库, 迁移到正在使用的库就不行了, 而且 rdb 里面是所有的 db, ...

  3. IE haslayout的理解与bug修复

    要想更好的理解 css, 尤其是 IE 下对 css 的渲染,haslayout 是一个非常有必要彻底弄清楚的概念.大多 IE下的显示错误,就是源于 haslayout 什么是 haslayout ? ...

  4. 微服务Kong(二)——快速入门

    在本节中,您将学习如何管理您的KONG实例.首先,我们将指导您如何启动Kong,以便您能访问KONG的RESTful形式的管理界面,您可以通过它来管理您的API,consumers等.通过管理型API ...

  5. 2-4 js基础-事件对象小结

    var e=ev||event; e.cancelBubble=true; document.documentElement   html document.body                  ...

  6. log4php0.9的详细配备实例说明

    一.什么是log4php: log4j在JAVA中可算是大名鼎鼎的日志开发包了,它为apche组织维护项目,VxR兄使用php来实现了log4j的功能, 目前log4php已经作为log4j的一个子项 ...

  7. 微信小程序——动画操作时,rpx 和 px 的转换计算。

    嫌长版本: var rpx = 10000; var systemInfo = wx.getSystemInfoSync(); var px = rpx / 750 * systemInfo.wind ...

  8. 折半插入排序-ACM题

    第一种实现方式:(本人一开始对cin的使用不是很熟悉,看了一些人得博客详解后才有了第一种方式的实现,自己都被惊讶到了so easy:题目在下面) // // main.cpp // BinaryIns ...

  9. 【SSH网上商城项目实战22】获取银行图标以及支付页面的显示

        转自: https://blog.csdn.net/eson_15/article/details/51452243 从上一节的小demo中我们搞清楚了如何跟易宝对接以及易宝的支付流程.这一节 ...

  10. unity3d之使用技巧

    知乎 project.hierarchy折叠打开全部文件夹——alt +方向键