使用元数据简化jdbc代码---查询操作(用到反射)
使用元数据简化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代码---查询操作(用到反射)的更多相关文章
- [原创]java WEB学习笔记109:Spring学习---spring对JDBC的支持:使用 JdbcTemplate 查询数据库,简化 JDBC 模板查询,在 JDBC 模板中使用具名参数两种实现
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Java 使用JDBC连接查询操作数据
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.sql. ...
- JDBC最原始的代码做查询操作
首先编写一个User类. public class User { private String username; private String password; public String get ...
- 结合java的反射和泛型性质简化JDBC和相应的同步等服务器数据库操作代码
github地址:https://github.com/hzphzp/HeartTrace_Server 我们的服务器端数据库并没有用sqllite, 而是直接用mysql,并且用JDBC直接进行操作 ...
- JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...
- 使用Spring简化JDBC操作数据库
Spring的开发初衷是为了减轻企业级开发的复杂度,其对数据库访问的支持亦如此,使用Spring访问数据库能带来以下好处: 1.1 简化代码 使用原生的JDBC访问数据库,一般总是要执行以下步 ...
- 【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
转自:http://www.cnblogs.com/ysw-go/ JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 ...
- MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- 使用Spring JDBCTemplate简化JDBC的操作
使用Spring JDBCTemplate简化JDBC的操作 接触过JAVA WEB开发的朋友肯定都知道Hibernate框架,虽然不否定它的强大之处,但个人对它一直无感,总感觉不够灵活,太过臃肿了. ...
随机推荐
- happy in java之io流简介
闲来没事,重温马士兵老师的java基础... 流 水流的流 流氓的流,,流 英文叫做stream,溪流 流的分类: 流是用来读写数据的. 流就像水流一样,File类封装的是文件的名字,它是内存里头 ...
- 安装Postgresql之后,创建用户 配置rails
登录 sudo su - postgres psql 1 创建Postgresql新用户,devpg是用户名,密码也是devpg, 不是超级管理员,拥有创建数据库权限,登录权限,继承拥有角色权限 cr ...
- 【PhotoShop】模糊图片清晰处理
1.Ctrl+J复制出背景副本.对副本模式选择“亮度”. 2.选择“滤镜”菜单下的“锐化>USM锐化”命令,在设置窗口中适当调节一下锐化参数,根据你原图模糊的情况来调节,本图采用锐化数量为“15 ...
- js中进行金额计算
js中进行金额计算parseFloat 在js中进行以元为单位进行金额计算时 使用parseFloat会产生精度问题var price = 10.99;var quantity = 7;var n ...
- C# 泛型使用笔记
泛型的基本概念我就不在这重复了,不了解的同学请自行百度. 我主要写下我在项目中要到的泛型实例.献丑了.....有什么不好或不对的地方大家尽可评论留言. 为什么要用泛型? 通过使用泛型,我们可以极大地提 ...
- [C语言] 数据结构-预备知识结构体
结构体 为什么出现结构体 为了表示一些复杂的数据,而普通的基本类型变量无法满足需求 什么叫结构体 结构体是用户根据实际需要自己定义的复合数据类型 如何使用结构体 1.两种方式 一般使用结构体指针的形 ...
- 给<input>文本框添加灰色提示文字
value="你的提示文字" onFocus="if(value==defaultValue){value='';this.style.color='#000'}&quo ...
- 微信小程序二维码识别
目前市场上二维码识别的软件或者网站越来越多,可是真正方便,无广告的却少之很少. 于是,自己突发奇想做了一个微信二维码识别的小程序. 包含功能: 1.识别二维码 ①普通二维码 ②条形码 ③只是复制解析出 ...
- K:求取两个数的最大公约数的两个算法
相关介绍: 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为gcd(a,b).同样的,a,b,c的最大公约数记为gcd(a,b,c),多个整数的最 ...
- eclipse中编写运行c/c++
注意:此过程有点复杂 准备:1.MinGW:c/c++运行环境: 2.CDT 1.MinGW:安装程序:http://sourceforge.net/projects/mingw/?source=ty ...