zoukankan      html  css  js  c++  java
  • JDBC(5)—DatabaseMetaData

    • 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);
        }
    }
    
  • 相关阅读:
    ACM集训的第一题
    python作用域
    python——异常类型
    PycharmV2017 1.x使用说明
    python之路——面向对象(进阶篇)
    python之路——面向对象(基础篇)
    python学习之路——基础篇(3)模块(续)
    python之路——基础篇(2)模块
    Python学习之路——基础篇(1)字符串格式化
    初学设计模式:策略模式
  • 原文地址:https://www.cnblogs.com/tengpengfei/p/10454020.html
Copyright © 2011-2022 走看看