<五>JDBC_利用反射及JDBC元数据编写通用的查询方法
此类针对javaBean类写了一个通用的查询方法,List<javaBean> 通用查询更新中...;通过学习,深刻体会到学会反射就等于掌握了java基础的半壁江山!
一、使用JDBC驱动程序处理元数据:
* .java通过JDBC获得连接后得到一个Connection对象,可以从这个对象获得有关数据库管理系统的各种信息,
* 包括数据库的各个表,表中的各个列,数据类型,触发器,存储过程等各方面的信息。根据这些信息,JDBC可以访问
* 一个事先并不了解的数据库。
* .获取这些信息的方法都是在DataBaseMetaData类的对象上实现的,而DataBaseMetaData对象是在
* Connection对象上获得的。
二、ResultSetMetaData类
* .是描述ResultSet的元数据对象,可用于获取ResultSet对象中列的类型和属性信息的对象:
* ---getColumnName(int column) :获取指定列的名称
* ---getColumnCount() : 返回当前ResultSet对象中的列数
* ---getColumnLabel(int column) : 获取指定列的别名(索引从1开始)
* ---getColumnTypeName() : 检索指定列的数据库特定的类型名称
* ---getColumnDisplaySize() : 指示指定列的最大标准宽度,以字符为单位
* ---isNullable(int column) : 指示指定列中的值是否可以为null
* ---isAutoIncrement() : 指示是否自动为指定列进行编号,这样这些列仍然是只读的。
*
* 调用ResultSet的getMetaData()方法得到ResultSetMetaData对象。
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;
public class JDBCTest2 {
@Test
public void testGet(){
String sql="select id,name,email,birth from customers where id=?";
Customer customer=get(Customer.class,sql,2);
System.out.println(customer);
/*
* **FlowID对应数据库表属性字段,要求别名(flow_Id)对应javaBean的属性名**
* 解析sql语句中列的别名、值,再通过反射技术把值赋给对应的属性,详细过程如下:
* 1、先利用SQL语句进行查询,得到结果集
* 2、利用反射创建实体类的对象
* 3、获取结果集列的别名
* 如何获取?
* 4、再获取结果集的每一列的值,结合3得到一个Map,键:列的别名,值:列的值
* 5、再利用反射为2的对应的属性赋值,属性即为Map的键,值即为Map的值。
* */
sql="select FlowId flow_Id,Type,IDCard,ExamCard,StudentName from examstudent where FlowId=?";
Student stu=get(Student.class,sql,1);
System.out.println(stu);
}
public <T> T get(Class<T> clazz, String sql,Object... args){
/* 0、得到ResultSet对象
* 1、得到ResultSetMetaData的对象
* 2、创建一个Map<String,Object>对象
* 3、处理结果集,利用ResultSetMetaData填充2对应的Map对象
* 4、若Map不为空集,利用反射创建clazz对应的对象
* 5、遍历Map对象,利用反射为Class对象对应的属性赋值
*
* */
T entity=null;
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
con=JDBCTools.getConnection();
ps=con.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
ps.setObject(i+1, args[i]);
}
rs=ps.executeQuery();
ResultSetMetaData rsmd=rs.getMetaData();
Map<String,Object> values=new HashMap<>();
//因获取的是一个类...,所以if非while
if(rs.next()) {
for (int i = 0; i < rsmd.getColumnCount(); i++) {
String columnLabel=rsmd.getColumnLabel(i+1);
Object columnValue=rs.getObject(i+1);
values.put(columnLabel, columnValue);
}
}
//若Map不为空
if (values.size()>0) {
entity=clazz.newInstance();
//为javaBean的属性赋值
for (Map.Entry<String, Object> entry:values.entrySet()) {
String fieldName=entry.getKey();
Object value=entry.getValue();
ReflectionUtils.setFieldValue(entity, fieldName, value);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCTools.release(rs, ps, con);
}
return entity;
}
}
帮助工具类
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* 反射的 Utils 函数集合
* 提供访问私有变量, 获取泛型类型 Class, 提取集合中元素属性等 Utils 函数
* @author Administrator
*
*/
public class ReflectionUtils {
/**
* 通过反射, 获得定义 Class 时声明的父类的泛型参数的类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param clazz
* @param index
* @return
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index){
Type genType = clazz.getGenericSuperclass();
if(!(genType instanceof ParameterizedType)){
return Object.class;
}
Type [] params = ((ParameterizedType)genType).getActualTypeArguments();
if(index >= params.length || index < 0){
return Object.class;
}
if(!(params[index] instanceof Class)){
return Object.class;
}
return (Class) params[index];
}
/**
* 通过反射, 获得 Class 定义中声明的父类的泛型参数类型
* 如: public EmployeeDao extends BaseDao<Employee, String>
* @param <T>
* @param clazz
* @return
*/
@SuppressWarnings("unchecked")
public static<T> Class<T> getSuperGenericType(Class clazz){
return getSuperClassGenricType(clazz, 0);
}
/**
* 循环向上转型, 获取对象的 DeclaredMethod
* @param object
* @param methodName
* @param parameterTypes
* @return
*/
public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes){
for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
try {
//superClass.getMethod(methodName, parameterTypes);
return superClass.getDeclaredMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
//Method 不在当前类定义, 继续向上转型
}
//..
}
return null;
}
/**
* 使 filed 变为可访问
* @param field
*/
public static void makeAccessible(Field field){
if(!Modifier.isPublic(field.getModifiers())){
field.setAccessible(true);
}
}
/**
* 循环向上转型, 获取对象的 DeclaredField
* @param object
* @param filedName
* @return
*/
public static Field getDeclaredField(Object object, String filedName){
for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){
try {
return superClass.getDeclaredField(filedName);
} catch (NoSuchFieldException e) {
//Field 不在当前类定义, 继续向上转型
}
}
return null;
}
/**
* 直接调用对象方法, 而忽略修饰符(private, protected)
* @param object
* @param methodName
* @param parameterTypes
* @param parameters
* @return
* @throws InvocationTargetException
* @throws IllegalArgumentException
*/
public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes,
Object [] parameters) throws InvocationTargetException{
Method method = getDeclaredMethod(object, methodName, parameterTypes);
if(method == null){
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]");
}
method.setAccessible(true);
try {
return method.invoke(object, parameters);
} catch(IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
return null;
}
/**
* 直接设置对象属性值, 忽略 private/protected 修饰符, 也不经过 setter
* @param object
* @param fieldName
* @param value
*/
public static void setFieldValue(Object object, String fieldName, Object value){
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
try {
field.set(object, value);
} catch (IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
}
/**
* 直接读取对象的属性值, 忽略 private/protected 修饰符, 也不经过 getter
* @param object
* @param fieldName
* @return
*/
public static Object getFieldValue(Object object, String fieldName){
Field field = getDeclaredField(object, fieldName);
if (field == null)
throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]");
makeAccessible(field);
Object result = null;
try {
result = field.get(object);
} catch (IllegalAccessException e) {
System.out.println("不可能抛出的异常");
}
return result;
}
}
总结:
1、why:如果只有一个结果集。但不知道结果集中有多少列,列的名字都是什么?
1>编写通用的查询方法时需要使用;
public <T> T get(Class<T> clazz,String sql,Object...sql)
2、what:用于描述ResultSet的对象。
3、how
1>得到ResultSetMetaData对象:调用ResultSet的getMetaData()方法
ResultSetMetaData rsmd=resultSet.getMetaData();
2>ResultSetMetaData有哪些好用的方法:
>int getColumnCount()结果集中包含哪些列
>String getColumnLabel(int column):获取指定列的别名,其中索引从1开始。
<五>JDBC_利用反射及JDBC元数据编写通用的查询方法的更多相关文章
- Java -- JDBC_利用反射及 JDBC 元数据编写通用的查询方法
先利用 SQL 进行查询,得到结果集: 利用反射创建实体类的对象:创建对象: 获取结果集的列的别名: 再获取结果集的每一列的值, 结合 3 得到一个 Map,键:列的别名,值:列的值: 再利用反射为 ...
- JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 * 可以由Connection得到 */ 具体的应用代码: @Te ...
- 【转】JDBC学习笔记(5)——利用反射及JDBC元数据编写通用的查询方法
转自:http://www.cnblogs.com/ysw-go/ JDBC元数据 1)DatabaseMetaData /** * 了解即可:DatabaseMetaData是描述数据库的元数据对象 ...
- MYSQL 之 JDBC(六): 增删改查(四)利用反射及JDBC元数据编写通用的查询
1.先利用SQL进行查询,得到结果集2.利用反射创建实体类的对象:创建Student对象3.获取结果集的列的别名:idCard.studentName4.再获取结果集的每一列的值,结合3得到一个Map ...
- 利用反射及jdbc元数据实现通用的查询方法
---------------------------------------------------------------------------------------------------- ...
- JDBC--利用反射及JDBC元数据编写通用的查询方法
1.JDBC元数据(ResuleSetMetaData):描述ResultSet的元数据对象,可以从中获取到结果集中的列数和列名等: --使用ResultSet类的getMetaData()方法获得R ...
- java攻城狮之路--复习JDBC(利用BeanUtils、JDBC元数据编写通用的查询方法;元数据;Blob;事务;批量处理)
1.利用BeanUtils的前提得要加入以下两个jar包: commons-beanutils-1.8.0.jar commons-logging-1.1.1.jar package com.shel ...
- 利用反射及JDBC元数据编写通用查询方法
元数据:描述数据的数据,ResultSetMetaData是描述ResultSet的元数据对象,从它可以得到数据集有多少了,每一列的列名... ResultSetMetaData可以通过ResultS ...
- JDBC课程5--利用反射及JDBC元数据(ResultSetMetaData)编写通用的查询方法
/**-利用反射及JDBC元数据编写通用的查询方法 * 1.先利用SQl语句进行查询,得到结果集--> * 2.查找到结果集的别名:id--> * 3.利用反射创建实体类的对象,创建aut ...
随机推荐
- 亲历腾讯WEB前端开发三轮面试经历及面试题
[一面]~=110分钟 2014/09/24 11:20 星期三 进门静坐30分钟做题. 填空题+大题+问答题 >>填空题何时接触电脑 何时接触前端运算符 字符串处理 延 ...
- CentOS6.3 编译安装LAMP(2):编译安装 Apache2.2.25
所需源码包: /usr/local/src/Apache-2.2.25/httpd-2.2.25.tar.gz 编译安装 Apache2.2.25 #切换到源码目录 cd /usr/local/src ...
- 【Alpha版本】冲刺-Day10
队伍:606notconnected 会议时间:11月18日 会议总结 张斯巍(433) 今天安排:完成剩余界面的设计,小修小补 完成度:100% 遇到的问题:无 感想:因为自己是负责界面美工部分的, ...
- mongDB-- 3. 查询操作
1. 准备工作 (1)启动mongo 进入mongo安装目录的bin/ 目录 , ./mongod (2)启动mongo客户端 ./mongo (3) 查看所有库 show dbs; (4) 切换到l ...
- wdcp安装memcached解决办法
1.下载libevent-1.4.14b-stable.tar.gz和memcached-1.4.15.tar.gz这两个文件,上传到服务器,并给它一个可用的下载地址, 如http://地址/memc ...
- jsonp 自己写的一个例子
function test(){ alert("13"); $.ajax({ type : "GET", async:false, url : "ht ...
- angularjs 弹出框 $modal 参数(转)
angularjs 弹出框 $modal $modal只有一个方法:open,该方法的属性有: templateUrl:模态窗口的地址 template:用于显示html标签 scope:一个作用 ...
- samtools常用命令详解
samtools的说明文档:http://samtools.sourceforge.net/samtools.shtmlsamtools是一个用于操作sam和bam文件的工具合集.包含有许多命令.以下 ...
- LeetCode 219 Contains Duplicate II
Problem: Given an array of integers and an integer k, find out whether there are two distinct indice ...
- 51nod1088(最长回文子串)
题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1088 题意: 中文题目诶~ 思路: 这道题字符串长度限定为1 ...