ResultSetMetaData和ResultSet
我现在有一张表t_product;我们查询所有的商品:SELECT * FROM t_product;
上述所有的数据都可以封装成一个对象,我们称这个查询出来的对象为结果集对象:ResultSet.
对于Java实现查询来说,sql语句是不同的,比如select * from t_product;或者select * from t_product where id=? and name=?;等等。?的个数是不同的,而且不可控制的,结果集合又是不一样的;那么我们如何实现呢?在这里我给出两中实现方案:
方案1:ResultSet单纯实现:
分析:单个未知的参数,sql语句,结果集对象,参数的个数;首先我定义一个接口,用来专门处理结果集对象;
/**
* 1 使用泛型声明接口,所有关于查询的类都可以使用该接口
* 2 传入结果集对象
* 3 返回结果使用泛型,具体的返回交给子类实现
* @param <T>
*/
public interface ResultSetHandler<T> {
T handler(ResultSet rs) throws SQLException;
}
接下来我们就专门的查询写一个方法:传递这三个位置的参数,由于预编译参数个数不确定,这里我们使用可变参数:
public static <T> T templateDQL(String sql,ResultSetHandler<T> handler,Object...args){
List<T> list=new ArrayList();
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
conn=DBUtils.getConn();
ps=conn.prepareStatement(sql);
for (int i=0;i<args.length;i++){
ps.setObject(i+1,args[i]);
}
/**执行sql语句*/
rs = ps.executeQuery();
return handler.handler(rs);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
上面的代码先获取连接对象,然后预编译,接着应该是将sql中的?变换成实际值;由于?的个数我们不知道,所以我使用了Object[]数组;使用for循环取出这些?。然后一一赋值;执行完毕sql之后,此时我们需要处理结果集。我们返回这个调用结果,让子类实现;
public class ProductDAOImpl implements IProductDAO {
private ResultSetHandler<List<Product>> rsh=new ResultSetHandlerManager(); public List<Product> getAll() {
String sql="select * from t_product ";
return JDBCTemplate.templateDQL(sql, rsh);
}
/**
* 结果集处理器
*/
class ResultSetHandlerManager implements ResultSetHandler<List<Product>>{
@Override
public List<Product> handler(ResultSet rs) throws SQLException {
List<Product> list=new ArrayList<>();
while (rs.next()){
Product product=new Product();
list.add(product);
/** rs是结果集对象。*/
/** 商品的id*/
Long id = rs.getLong("id");
/** 商品名称*/
String name = rs.getString("name");
/** 商品描述*/
String descs = rs.getString("descs");
/** 商品价格*/
double price = rs.getDouble("price");
/** 商品的状态*/
int status = rs.getInt("status");
/** 库存量*/
int storeNum = rs.getInt("storeNum");
product.setId(id);
product.setPrice(price);
product.setName(name);
product.setStatus(status);
product.setDescs(descs);
product.setStoreNum(storeNum);
}
return list;
}
}
}
getAll()方法调用templateDQL(sql, rsh);传入结果集对象,我们在这里定义了rsh.里面封装了一个List,list中保存product对象;具体实现交给ResultSetHandlerManager内部类来实现;对于上述的执行流程我可以画一个时序图来描述;
至此完成实现第一种的方案;第一种方案处理结果集合我忍为比较麻烦,但是其中的面向对象的思想还是值得学习的,接下来我来说明第二种的实现方案:
方案1:ResultSet和ResultSetMetaData一起来实现:
ResultSetMetaData是什么东西呢?该对象表示列对象;封装了一个表的列信息,比如id,name.age等等;
public class BaseDao{ public <T> List<T> getObjectForList(Class clz,String sql, Object... args){ List<T> list = null;//要返回的List集合
Connection con = null;//连接对象
PreparedStatement ps = null;//预编译对象
ResultSet resultSet = null;//结果集对象
T entity = null;//javabean对象(泛型)
conn=DBUtils.getConn();
ps=conn.prepareStatement(sql);
//设置参数
prepareStateSetArgs(ps,args)
//执行sql语句,返回结果集合对象
resultSet = ps.executeQuery();
// 获取该结果集的列对象
ResultSetMetaData rsmd = resultSet.getMetaData();
while (resultSet.next()) {
//将结果集合对象和列对象转化内成为Map集合
Map<String, Object> values = putOneResultSetToMap(resultSet, rsmd);
if (!values.isEmpty()) {
//将Map转化为对象,添加到List中;
entity = transferMapToBean(clazz,values);//将Map转化为bean的方法请大家自行实现
list.add(entity);
}
}
} private void prepareStateSetArgs(PreparedStatement ps, Object... args) throws SQLException {
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
}
private Map<String, Object> putOneResultSetToMap(ResultSet resultSet, ResultSetMetaData rsmd) throws SQLException {
Map<String, Object> values = new HashMap<String, Object>(); for (int i = 0; i < rsmd.getColumnCount(); i++) {
// 循环,获取列及对应的列名
String columnLabel = rsmd.getColumnLabel(i + 1);
// 循环,根据列名从ResultSet结果集中获得对应的值
Object columnValue = resultSet.getObject(columnLabel);
// 列名为key,列的值为value
values.put(columnLabel, columnValue);
}
return values;
}
}
第一种方式是怎么处理结果集合呢?简单的说就是通过列的名称获取列的值,如通过 id获取Long id,然后封装到Product对象;现在的做法是通过结果集合获取列对象,通过列对象获取所有的列,然后循环遍历,然后根据列名获取列的值,以列名为key,列值为value.封装到map当中,最后将map转化为我们所需要的对象;其实两种方案最本质的区别是第一种方案直接返回对象,第二种方案是直接返回Map,然后将Map转化为对象
ResultSetMetaData和ResultSet的更多相关文章
- oracle学习笔记(八)——结果集元数据ResultSetMetaData以及ResultSet转为对应的实体类框架
介绍 可用于获取关于 ResultSet 对象中列的类型和属性信息的对象,在持久框层框架(如:mybatis, hibernate)中被广泛的应用. 常用方法 int getColumnCount() ...
- ResultSet相关ResultSetMetaData详细
DatabaseMetaData 有关整个数据库的信息:表名.表的索引.数据库产品的名称和版本.数据库支持的操作. ResultSet 关于某个表的信息或一个查询的结果.您必须逐行访问数据行,但是您可 ...
- ResultSet
在Java中,获得ResultSet的总行数的方法有以下几种. 第一种:利用ResultSet的getRow方法来获得ResultSet的总行数 Java代码Statement stmt = con. ...
- java ResultSet获得总行数
在Java中,获得ResultSet的总行数的方法有以下几种. 第一种:利用ResultSet的getRow方法来获得ResultSet的总行数 Statement stmt = con.create ...
- JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法
/**-利用反射及JDBC元数据编写通用的查询方法 * 1.先利用SQl语句进行查询,得到结果集--> * 2.查找到结果集的别名:id--> * 3.利用反射创建实体类的对象,创建aut ...
- Java如何获取ResultSet结果中的每一列的数据类型
示例代码片段: ResultSet resultSet = statement.executeQuery(sql); ResultSetMetaData metaData = resultSet.ge ...
- Resultset获取行数和列数
在Java中,获得ResultSet的总行数的方法有以下几种. 第一种:利用ResultSet的getRow方法来获得ResultSet的总行数 Statement stmt = con.create ...
- 轻量级DAO层实践初体验
最近快被 Hibernate 给坑哭了,有了自己动手实现 ORM 映射 DAO 的冲动. 工作之余折腾了快一星期,总算是有点小成就. 现打算将过程记录下来,方便自己后续回顾填补遗漏. 1. 传统 JD ...
- <五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...:通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山! 一.使用JDBC驱动 ...
随机推荐
- JETSON TK1 ~ 基于eclipse下开发ROS
此文档是在PC端开发后移植到TK1,并非在TK1上安装eclipse 官方使用IDE开发的文档: http://wiki.ros.org/IDEs 一:安装eclipse 1.下载eclipse安装包 ...
- [原创]java WEB学习笔记17:关于中文乱码的问题 和 tomcat在eclipse中起动成功,主页却打不开
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- 第一篇 dom
文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式.我们最为关心的是,DOM把 ...
- vo类总结
1.Camera类 camera类里面,首先camera有5个变量,fx_,fy_,cx_,cy_,depth_scale_5个变量,由外部传fx,fy,cx,cy,depth_scale给它.定义了 ...
- Centos7 配置yum源 安装epel
一.什么是epel如果既想获得 RHEL 的高质量.高性能.高可靠性,又需要方便易用(关键是免费)的软件包更新功能,那么 Fedora Project 推出的 EPEL(Extra Packages ...
- 算法(Algorithms)第4版 练习 1.4.1
=N(N-1)(N-2)/6
- 关于ansible变量的一个问题
ansible-playbook 使用with_items 时 items中 如果有变量 {} 外面可以用 “” items中 如果都是固定值,没有用到变量,{}最外面不要加 “” ,不然报错,mmp
- jquery详解图片平滑滚动
jquery详解图片平滑滚动 随便写了个DOM,没有美观性,见谅 原理: 1.定义两组ul列表放图,第一个ul放5张图,第二个ul为空 2.为什么要用两个ul?因为要用到jQuery的克隆方法clon ...
- 分享知识-快乐自己:Liunx 安装 Zookeeper
Zookeeper可以安装在windows中也可以安装在linux中! 但是我们的服务器基本都是在linux之上 安装我们的 zookeeper 注册中心! 安装成功之后 修改 nat 模式对应的端 ...
- js修改css时如何考虑兼容性问题es5+es6
es5的写法 var elementStyle = document.createElement('div').style var vendor = (function(){ let transfor ...