• 1.简介:

    使用元数据已实现通用的查询方法。元数据介绍:使用jdbc获得连接之后,得到一个Connection对象,可以通过这个对象获得DataBaseMetaData对象,该对象可以获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列,数据类型触发器,存储过程等各方面的信息,根据这些信息JDBC可以访问一个事先并不了解的的数据库。

    ** 这样通过这种方法,可以让即使只知道类名、SQL语句,也可以数据表中的字段和类成员变量联系到一起。从而查询出结果来。可以把查询出来的数据与成员变量联系到一块,可以把成员变量的名作为数据表列别名写道SQL语句中,通过DataBaseMateData对象获取列别名和列值存储到Map中,在通过反射创建对象,通过反射根据Map中取出的列别名获取指定的成员变量,再把列值赋给成员变量。

    //首先通过反射获取指定名称的变量。

    Field Name = entity.getClass().getDeclaredField(fieldName);

    //设置私有的变量允许访问。

    Name.setAccessible(true);

    //Name调用set(对象,值)方法,为获取到的变量赋值

    Name.set(entity, fieldValue);

    为什么要这样麻烦呢?其目的就是为了降低耦合性、提高可重用性。 **

  • 2.方法:

    获取这些信息都是在DataBaseMateData类的对象上实现的,而DataBaseMateData对象是在Connection对象上获得的。具体使用时使用ResultSetMateData类。

    *可用于获取ResultSet对象(结果集)中列的类型和属性信息的对象:

    *常用方法方法:

    • getColumnName(int column):获取指定列的名称
    • getColumnCount():返回当前ResultSet对象中的列数
    • getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
    • getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
    • isNullable(int column):指示指定列中的值是否可以为null。
    • isAutoIncrement(int column):指示是否为指定列进行编号,这样这些列仍然是只读的。

      *

      *具体使用时是使用ResultSetMetaData类

      *该类方法:

      *int getColumn():SQL 语句中包含哪些列

      *String getColumnLabel(int column):获取指定类别名,其中索引从1开始。
  • 3.步骤:

    • ①.得到ResultSetMetaData对象,该对象通过ResultSet对象调用getMetaData()来得到,且该对象包含所查询的数据表的所有信息。
    • ②.创建一个Map < String, Object>对象,键:列别名 值:列的值
    • ③.处理结果集,利用ResultSetMetaData填充3对应的Map对象,ResultSetMetaData对象调用getColumnLabel(int) 获取键:列别名ResultSet对象调用getObject()方法获取值:列中值。把键值对存到Map中去。
    • ④.若Map不为空集,利用反射创建clazz对应的对象。 类名.class.newInstance()。
    • ⑤.遍历Map对象,利用反射为Class对象的对应的属性赋值
  • 4.why:

    为什么要使用这个类,因为查询时方法类似,很多代码雷同,重复的代码太多。

  • 5.what:

    通用的查询方法,可以根据传入的SQL、SQL是占位符的值、Class对象返回SQL对应的记录的对象。

    • ①方法签名:public T ResultSetMetaData(Class clazz,String sql,Object … args)
  • 6.how:

    • ①:根据连接(connection)创建PreparedStatement对象。
    • ②:设置sql语句的占位符的值。
    • ③:通过PreparedStatement对象执行查询得到ResultSet对象(结果集)。
    • ④:ResultSet对象调用getMetaData获得ResultSetMetaData对象,该对象包含所查询的数据表的信息。
    • ⑤:创建一个Map < String, Object>对象,键:列别名 值:列的值。
    • ⑥:处理结果集,利用ResultSetMetaData填充3对应的Map对象,处理多个列。
    • ⑦:若Map不为空集,利用反射创建clazz对应的对象。
    • ⑧:遍历Map对象,利用反射为Class对象的对应的属性赋值。
    • ⑨:关闭链接。
  • 总结:使用反射获取到列别名和列值,存到集合中,再把集合中的数据赋给类成员变量

  • 实例:

public class DataBaseMetaData_5 {

    /**
* 1.DataBaseMetaData是描述数据库的元数据对象,测试DataBaseMetaData类的一些基本方法。
* 了解
*/
@Test
public void testDataBaseMetaData(){
Connection conn = null;
DatabaseMetaData dbmd = null;
ResultSet rs = null;
try {
conn = TestTools.getConnection();
dbmd = conn.getMetaData();
//获取驱动连接
System.out.println("驱动:"+dbmd.getURL());
//查看数据库版本号
System.out.println("版本号:"+dbmd.getDatabaseMajorVersion());
//查看MySql中有哪些数据库
rs = dbmd.getCatalogs();
while(rs.next()){
System.out.println("数据库:"+rs.getString(1));
} //.... } catch (Exception e) {
e.printStackTrace();
}finally{
TestTools.release(null, conn);
}
}
/**
* 2.ResultSetMetaData是描述结果集的元数据对象
*可以得到结果集的基本信息,比如结果集中有那些列、列名、别名、列值
*掌握
*/
@Test
public void ResultSetMetaData(){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = TestTools.getConnection();
String sql = "select id, name, age, birth, address from customers";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
//1.得到ResultSetMetaData对象
ResultSetMetaData rsmd = rs.getMetaData();
//2.获得列个数
System.out.println("列数:"+rsmd.getColumnCount());
//3.获得列名
for(int i = 0; i < rsmd.getColumnCount(); i++){
System.out.println("第"+(i+1)+"列别名:"+rsmd.getColumnLabel(i + 1));
}
//4.获得列别名
for(int i = 0; i < rsmd.getColumnCount(); i++){
System.out.println("第"+(i+1)+"列名:"+rsmd.getColumnName(i + 1));
}
} catch (Exception e) {
e.printStackTrace();
}finally{
TestTools.release(rs, ps, conn);
}
} /**
* 3.获取Student对象对应的数据表中的根据SQL语句查询到的记录信息。
* 获取ResultSetMetaData对象,并且调用getMetaData()方法,获取所有列的信息(主要是列名)
*把得到的列名存到集合HashMap()中。
*/
@Test
public void testResultSetMetaData(){
Student student = null;
Connection conn = null;
Statement state = null;
ResultSet rs = null;
try {
conn = TestTools.getConnection();
state = conn.createStatement();
String sql = "select * from examStudent";
rs = state.executeQuery(sql); //1.得到ResultSetMetaData对象,该对象包含了数据库表的一些信息
ResultSetMetaData rsmd = rs.getMetaData();
//2.创建一个Map<String, Object>对象,键:列别名 值:列的值
Map<String, Object> values = new HashMap<String, Object>();
//3.处理结果集,利用ResultSetMetaData填充3对应的Map对象
while(rs.next()){//若有多个对象,则处理多个对象
//处理多个列
for(int i = 0; i < rsmd.getColumnCount(); i++){
String columnLabel = rsmd.getColumnLabel(i + 1);//列从1开始
Object columnValues = rs.getObject(columnLabel);
values.put(columnLabel, columnValues);
}
//System.out.println(values);
} //4.若Map不为空集,利用反射创建clazz对应的对象。
Class clazz = Student.class;
student = (Student)clazz.newInstance(); //5.遍历Map对象,利用反射为Class对象的对应的属性赋值
for(Map.Entry<String, Object> entry : values.entrySet()){
String fieldName = entry.getKey();
Object fieldValue = entry.getValue();
//把存到Map集合中的元素赋值给Student对象的成员属性
TestTools.setFieldValue(student, fieldName, fieldValue);
}
//6.查看结果
//System.out.println(student.toString()); } catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.关闭连接
TestTools.release(rs, state, conn);
}
System.out.println(student);
} /**
* 4.对以上方法进行了修改,以增加通用性,以上方法只能获取Student的对象的,则该方法可以获取根据传入的Class来返回
*任意的对象。
*/
public <T> T ResultSetMetaData(Class<T> clazz,String sql,Object ... args){
T entity = null;
Connection conn = null;
PreparedStatement preparedstatement = null;
ResultSet rs = null;
//System.out.println(clazz+"--"+sql+"--"+args);
try {
conn = TestTools.getConnection();
preparedstatement = conn.prepareStatement(sql);
for(int i = 0;i < args.length; i++){
preparedstatement.setObject(i+1, args[i]);
}
rs = preparedstatement.executeQuery(); //1.得到ResultSetMetaData对象,该对象包含了数据库表的一些信息
ResultSetMetaData rsmd = rs.getMetaData();
//2.创建一个Map<String, Object>对象,键:列别名 值:列的值
Map<String, Object> values = new HashMap<String, Object>();
//3.处理结果集,利用ResultSetMetaData填充3对应的Map对象
while(rs.next()){//若有多个对象,则处理多个对象
//处理多个列
for(int i = 0; i < rsmd.getColumnCount(); i++){
String columnLabel = rsmd.getColumnLabel(i + 1);//列从1开始
Object columnValues = rs.getObject(columnLabel);
values.put(columnLabel, columnValues);
}
//System.out.println(values);
} //4.若Map不为空集,利用反射创建clazz对应的对象。
if(values.size() > 0){
entity = clazz.newInstance();
//5.遍历Map对象,利用反射为Class对象的对应的属性赋值
for(Map.Entry<String, Object> entry : values.entrySet()){
String fieldName = entry.getKey();
Object fieldValue = entry.getValue();
TestTools.setFieldValue(entity,fieldName,fieldValue);
//System.out.println(fieldName +":"+fieldValue);
}
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}finally{
//5.关闭连接
TestTools.release(rs, preparedstatement, conn);
}
return entity;
} /**
* 5.测试以上方法:只需要传入Class对象、sql语句、占位符即可
*/ @Test
public void test(){
String sql = "select * from examStudent where FlowID = ?";
Student student = ResultSetMetaData(Student.class,sql,33);
System.out.println(student);
}
}

JDBC(5)—DatabaseMetaData的更多相关文章

  1. 跟着刚哥学习Spring框架--JDBC(六)

    Spring的JDBC框架 Spring JDBC提供了一套JDBC抽象框架,用于简化JDBC开发. Spring主要提供JDBC模板方式.关系数据库对象化方式.SimpleJdbc方式.事务管理来简 ...

  2. JDBC (三)

    1 数据库连接池的原理 应用程序直接获取Connection的缺点: 缺点:用户每次请求都需要向数据库获取连接,而数据库创建连接通常需要消耗相对较大的资源,创建的时间较长.如果一个网站一天访问量是10 ...

  3. SoapUI接口测试之JDBC(三)

    JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用java语言编写的类和接口 ...

  4. 浅谈JDBC(一)

    一.JDBC技术引言 1.什么是JDBC技术 提供了一套接口规范,利用java代码进行数据库操作. 2.JDBC技术的核心思想 对于程序员来说,代码访问数据库分为三个步骤:1.通过数据库的账号密码.2 ...

  5. JDBC(一)之细说JDBC

    Properties info = new Properties();//要参考数据库文档 info.setProperty("user", "root"); ...

  6. JDBC(三)数据库连接池(DBCP、C3P0)

    前言 这段时间状态有一点浮躁,希望自己静下心来.还有特别多的东西还没有学懂.需要学习的东西非常的多,加油! 一.JDBC复习 Java Data Base Connectivity,java数据库连接 ...

  7. JAVA基础-JDBC(一)

    一.JDBC的简介 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,由与各种数据库都有着一套自己的规范,JAVA对其操 ...

  8. JDBC(四)

    1 Apache DBUtils框架 1.1 DBUtils简介 commons-dbutils是Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本非常低,并且使用db ...

  9. JDBC (二)

    1 使用JDBC进行批处理 当需要向数据库发送一批SQL语句的时候,应该避免向数据库一条条的发送执行,而应该采用JDBC的批处理机制,以提高执行效率. 实现批处理的方式一: Statement.add ...

随机推荐

  1. centos6.5/centos7安装部署企业内部知识管理社区系统wecenter

    企业内部知识系统wecenter社区系统安装及部署 centos 6.5环境安装 因为是公司内部使用在线人数不会太多,使用yum安装lamp环境即可 1.安装lamp基本环境 yum -y insta ...

  2. CGAffineTransform 缩放 / 旋转 / 平移

    CGAffineTransform此类是一个3*3矩阵的变换. - (void)transformImageView { CGAffineTransform t = CGAffineTransform ...

  3. 《Oracle 11g 入门到精通.明日科技.pdf》学习笔记

    本博文整理者:刘军 本博文出自于: <Oracle 11g 入门到精通>一书 声明:1:转载请标注出处.本文不得作为商业活动.本人不负法律责任.违法者自负一切法律责任. ————————— ...

  4. node path.resolve()

    作用: path.resolve()方法将一系列路径或路径段解析为绝对路径. 语法: path.resolve([from ...], to) 说明:将参数 to 位置的字符解析到一个绝对路径里. 参 ...

  5. 前端工程化-webpack(打包JS)(二)

    一.第一种打包方式 webpack entry<entry> output 假设目录结构如下: index.html是入口文件 打包app.js为bundle.js如下 app.js 当使 ...

  6. STL整理之map

    转载请注明出处,部分内容引自李煜东<算法竞赛进阶指南> 前置知识:    C++.C语言入门 Map是什么 Map是从键(key)到值(value)的映射,其内部实现是一棵以key为关键码 ...

  7. 步步为营-10-string的简单操作

    using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Tex ...

  8. Ubuntu 8.04嵌入式交叉编译环境arm-linux-gcc搭建过程图解

    Linux版本:Ubuntu8.04 内核版本:Linux 2.6.24 交叉编译器版本:arm-linux-gcc-3.4.1 交叉编译器下载链接: https://share.weiyun.com ...

  9. 依赖倒置原则(Dependence Inversion Principle,DIP)

    依赖倒转原则就是 A.要依赖于抽象,不要依赖于实现.(Abstractions should not depend upon details. Details should depend upon a ...

  10. BZOJ3091 城市旅行 LCT

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3091 题意概括 鉴于本人语文不好,此题的描述原题很清晰,废话不多,请看原题. 可怕,原题是图片,不 ...