• JDBC进阶 元数据


    1:resultSet

    1.1最基本的ResultSet.

    1.2 可滚动的ResultSet类型

    1.3 可更新的ResultSet

    1.4 可保持的ResultSet

    2:PrepareStatement

    2.1: 基本操作

    2.2 复用pststemetn

    2.3 性能分析

    3:执行批量SQL

    3.1: statemet 方式

    3.2: preparedstatement 方式

    4: 事物transaction

    4.1 基本处理

    4.2 断点事物处理

    6 元数据类型

    6.1 DatabaseMetaData  数据库元数据

    在表中列出列 getColumS()

    主键信息

    6.2 ParameterMetaData 参数元数据类型

    6.3 ResultSetMetaData 结果集元数据

    1:resultSet

    当创建一个ResultSet时,你可以设置三个属性:

     类型

     ResultSet.TYPE_FORWARD_ONLY   

     该常量指示光标只能向前移动的 ResultSet 对象的类型。

     ResultSet.TYPE_SCROLL_INSENSITIVE   

      该常量指示可滚动但通常不受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。

     ResultSet.TYPE_SCROLL_SENSITIVE

     该常量指示可滚动并且通常受 ResultSet 底层数据更改影响的 ResultSet 对象的类型。

     并发

     ResultSet.CONCUR_READ_ONLY

      该常量指示不可以更新的 ResultSet 对象的并发模式。

     ResultSet.CONCUR_UPDATABLE

      该常量指示可以更新的 ResultSet 对象的并发模式。

     可保存性

     ResultSet.HOLD_CURSORS_OVER_COMMIT

     该常量指示提交当前事务时,具有此可保存性的打开的 ResultSet 对象将保持开放。

     ResultSet.CLOSE_CURSORS_AT_COMMIT

      该常量指示提交当前事务时,具有此可保存性的打开的 ResultSet 对象将被关闭。

    在创建StatementPreparedStatement时已经设置了这些值,如下所示:

    Statement statement = connection.createStatement(
        ResultSet.TYPE_FORWARD_ONLY,
        ResultSet.CONCUR_READ_ONLY,
        ResultSet.CLOSE_CURSORS_OVER_COMMIT
       );
    
    PreparedStatement statement = connection.prepareStatement(sql,
        ResultSet.TYPE_FORWARD_ONLY,
        ResultSet.CONCUR_READ_ONLY,
        ResultSet.CLOSE_CURSORS_OVER_COMMIT
       );

    1.1最基本的ResultSet.

     最基本的ResultSet是因为,这个ResultSet他起到的作用就是完成了查询结果的存储功能,而且只能读去一次,不能够来回的滚动读取. 最常用的

     1.2 可滚动的ResultSet类型

     next(),previous(), first(),last()  移动绝对行 absolute(int n),移动相对行relative(int n),

     ResultSet.TYPE_FORWARD_ONLY

     只能向前滚动

     ResultSet.TYPE_SCROLL_INSENSITIVE

     实现任意的前后滚动, 对于修改不敏感

     Result.TYPE_SCROLL_SENSITIVE  

     实现任意的前后滚动, 对于修改敏感.

    1.3 可更新的ResultSet

    ResultSet对象可以完成对数据库中表的修改,但是我知道ResultSet只是相当于数据库中表的视图,所以并不时所有的ResultSet只要设置了可更新就能够完成更新的,能够完成更新的ResultSetSQL语句必须要具备如下的属性: 通过 并发下面属性设置

     a,只引用了单个表.

     b,不含有join或者group by子句.

     c,那些列中要包含主关键字.

     执行顺序UpdatXXX 更新操作执行必须执行

    1:moveToInsertRow()  是把ResultSet移动到插入行 这个插入行是表中特殊的一行
      moveToCurrentRow() 移动到插入行 如果之前Insert,那么就移动到之前Insert()0哪一行,没有Insert 就没有效果
    2:UpdateXXX()
    3:insertRow()

    1.4 可保持的ResultSet

     所有的Statement的查询对应的结果集是一个,如果调用Connectioncommit()方法也会关闭结果集.

     通过设置 HOLD_CURSORS_OVER_COMMIT 来保持数据

    2:PrepareStatement

    特点: 禁止了拼接SQL可以注入的现象,将会SQL传入数据库编译通过设置参数方式保证安全性

    select * from user where name='aa' and password='bb' or 1=1 //类始于这种SQL的注入方式

    2.1: 基本操作

     executeQuery()    执行查询

     executeUpdate()  执行CUD操作  

     execute() 执行DDL操作

     executeLargeUpdate() 执行超大SQL语句

      String sql = "select * from user";
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
    
                ResultSet resultSet = preparedStatement.executeQuery();
    
                while (resultSet.next()) {
                    int id = resultSet.getInt("id");
                    String username = resultSet.getString("username");
                    String birthday = resultSet.getString("birthday");
                    String sex = resultSet.getString("sex");
                    String address = resultSet.getString("address");
    
                    System.out.println("  " + username + " " + birthday + " " + sex
                            + " " + address);
                }

    2.2 复用pststemetn

          即为一次创建多次使用, 通过connection创建prepareStatement 多次使用 prepareStatement

     特点 参数可以变,但是SQl 是不变的

     PreparedStatement preparedStatement = connection.prepareStatement(sql);//创建prepareStatement
    
                preparedStatement.setString(1,"Fant.J");
                preparedStatement.setInt(2,27);
                int result = preparedStatement.executeUpdate(); // 第一次使用
                
                preparedStatement.setString(1,"Fant.J reUseTest");
                preparedStatement.setInt(2,27);
                preparedStatement.executeUpdate();//第二次使用  但是都是用的第一次创建ps 时的编译语句 

    2.3 性能分析

      PreparedStatementStatement的子类,区别:

     PreparedStatement  编译一次,可以将多条SQL语句汇聚到一起执行,提高执行效率

     Statement 是每一条SQL执行一次,100SQL 就要执行100

    两个级别的复用:

     JDBC驱动程序重新使用PreparedStatement

     数据库重用PreparedStatement

    3:执行批量SQL

               用到 addBatch()和executeBatch()方法   用于 Insert Update  Delete SQL的处理

      3.1: statemet 方式

    Statement statement = null;
    try{
        statement = connection.createStatement();
    
        statement.addBatch("update people set firstname='aaa' where id=123");
        statement.addBatch("update people set firstname='bbb' where id=456");
        statement.addBatch("update people set firstname='ccc'  where id=789");
    
        int[] recordsAffected = statement.executeBatch();  // 返回每个SQl执行后影响的元组数
    } finally {
        if(statement != null) statement.close();
    }

      3.2: preparedstatement 方式

    String sql = "update user set username=? where id=?";
    PreparedStatement preparedStatement = null;
    try{
        preparedStatement =connection.prepareStatement(sql);
    
        preparedStatement.setString(1, "aaa");
        preparedStatement.setLong  (2, 123);
        preparedStatement.addBatch();
    
        preparedStatement.setString(1, "bbb");
        preparedStatement.setLong  (2, 456);
        preparedStatement.addBatch();
    
        int[] affectedRecords = preparedStatement.executeBatch();// 返回每条语句执行影响的行数
    }finally {
        if(preparedStatement != null) {
            preparedStatement.close();
        }
    }

    4: 事物transaction

     对出现异常的SQL代码进行回退(可能系统异常),保证数据一致性

    4.1 基本处理

    Connection connection = ...
    try{
        connection.setAutoCommit(false);  // 这种处理方式 没有回滚点 出错将返回整个SQL代码
        // create and execute statements etc.
        connection.commit();
    } catch(Exception e) {
        connection.rollback();
    } finally {
        if(connection != null) {
            connection.close();
        }
    }

    4.2 断点事物处理

    Connection conn = JdbcUtils.getConnection();
            PreparedStatement ps = null;
            Savepoint savepoint=null;  //断点
            try {
                conn.setAutoCommit(false);
                savepoint = conn.setSavepoint();  //设置当前断点1 当然可以有多个断点
                ps = conn.prepareStatement("update account set balance = balance - ? where name=?");
                ps.setInt(1, 500);
                ps.setString(2, "Jack");
                ps.executeUpdate();
                //出现异常
                System.out.println(100 / 0);
                //给 rose 加钱
                ps = conn.prepareStatement("update account set balance = balance + ? where name=?");
                ps.setInt(1, 500);
                ps.setString(2,"Rose");
                ps.executeUpdate();
                //提交事务
                conn.commit();
                System.out.println("转账成功");
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    conn.rollback(savepoint);
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }finally {
                JdbcUtils.close(conn, ps);
            }
        }

    5 存储过程

    DELIMITER //   # 分割符号 默认是; 在多条语句时候需要进行改变 

    DELIMITER //   # 分割符号 默认是; 在多条语句时候需要进行改变 
    CREATE PROCEDURE findStuById(IN pid INTEGER)
    BEGIN
        SELECT * FROM student WHERE id=pid;
    END //
    DELIMITER ;

    通过Call关键字调用储存过程 CallableStatement处理存储过程     PreparedStatement ==处理DML DML DQL

    @Test
        public void test_producer() throws SQLException {
            Connection conn = JdbcUtils.getConnection();
            CallableStatement call = conn.prepareCall("CALL findStuByID(?)");
            
            call.setInt(1, 1);
            ResultSet resultSet = call.executeQuery();
            Student student=null;
            while(resultSet.next()) {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                boolean gender = resultSet.getBoolean("gender");
                Date birthday = resultSet.getDate("birthday");
                student= new Student(id, name, gender, birthday);
            }
            System.out.println(student);
        }

    6 元数据类型

    6.1 DatabaseMetaData  数据库元数据

     数据库基本信息

      Connection conn = JdbcUtils.getConnection();
    
    		DatabaseMetaData metaData = conn.getMetaData();
    
    		int majorVersion = metaData.getDatabaseMajorVersion();
    		String productVersion = metaData.getDatabaseProductVersion();
    		String driverName = metaData.getDriverName();
    		String url = metaData.getURL();
    		String userName = metaData.getUserName();
    		System.out.println(majorVersion);//8
    		System.out.println(productVersion);//8.0.13
    		System.out.println(driverName);//MySQL Connector/J
    		System.out.println(url);//jdbc:mysql://127.0.0.1:3306/day
    		System.out.println(userName);//root@localhost
    

      

    数据库所有信息的获取

      getTableTypes()   方法 可以使用正则表达式

        Connection conn = JdbcUtils.getConnection();
            DatabaseMetaData metaData = conn.getMetaData();
            // 
            String   catalog          = "day";  //对应数据库名称
            String   schemaPattern    = "*"; // mysql没有这个概念 sql server对应用户名称操作权限
            String   tableNamePattern = "student"; // 对应数据库名称
            String[] types            = {"TABLE"}; // 数据库中具体的类型 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。 
    
            ResultSet result = metaData.getTables(
                catalog, schemaPattern, tableNamePattern, types );
    
            while(result.next()) {
                String catalogName = result.getString(1);
                String schemaName = result.getString(2);
                String tableName = result.getString(3);
                String columName = result.getString(6);
                System.out.println(tableName);
                System.out.println(catalogName);
                System.out.println(columName);
            }

     在表中列出列 getColumS()

    Connection conn = JdbcUtils.getConnection();
            DatabaseMetaData metaData = conn.getMetaData();
            //
            String catalog = "day"; // 对应数据库名称
            String schemaPattern = "*"; // mysql没有这个概念 sql server对应用户名称操作权限
            String tableNamePattern = "student"; // 对应数据库名称
            String columnNamePattern = null;
    
            ResultSet result = metaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern);
    
            while (result.next()) {
                String columName = result.getString(4);// 列名称
                String data_type = result.getString(5);// 列类型
                System.out.println(columName);
                System.out.println(data_type);
            }

    主键信息

     getPrimaryKeys() 获取主键信息

     getExportedKeys() 获取外键信息

     Connection conn = JdbcUtils.getConnection();
            DatabaseMetaData metaData = conn.getMetaData();
            //
            String catalog = "day"; //执行库
            String schemaPattern = null; // mysql为null
            String tableNamePattern = "student";
    
            ResultSet result = metaData.getPrimaryKeys(catalog, schemaPattern, tableNamePattern);
            metaData.getExportedKeys(catalog, schema, table)
            while (result.next()) {
                String tablename = result.getString(3);// 表名
                String keyname = result.getString(4);//主键名
                System.out.println(tablename);
                System.out.println(keyname);

    6.2 ParameterMetaData 参数元数据类型

    对于传递的SQL中的参数(占位符? )的个数 数据进行处理

    前提:

     增加 &generateSimpleParameterMetadata=true

     所有的参数认为是字符串(VARCHAR)类型

     注意ParameterMetaData许多方法MySQL并不友好支持,比如像获取指定参数的SQL类型的getParameterType方法,如果数据库驱动连接URL只是简单的“jdbc:mysql://localhost:3306/jdbcdemo”那么MyEclipse会抛出SQLException异常,必须要将URL修改为“jdbc:mysql://localhost:3306/jdbcdemo?generateSimpleParameterMetadata=true”才行。但是像getParameterType等等与其他的方法也没多好用,因为如下面的例子,这些方法好像只会将所有的参数认为是字符串(VARCHAR)类型

    public void test_ParameterINFO() throws SQLException {
            Connection conn = JdbcUtils.getConnection();
            String sql="SELECT * FROM STUDENT WHERE id=?";
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            
            ParameterMetaData pMetaData = preparedStatement.getParameterMetaData();
            preparedStatement.setInt(1, 1);
      
            int count = pMetaData.getParameterCount();
            for(int i = 1; i <= count; i ++) {
                System.out.print(pMetaData.getParameterClassName(i) + "	");
                System.out.print(pMetaData.getParameterType(i) + "	");
                System.out.println(pMetaData.getParameterTypeName(i));
            }
            //执行查询操作
            preparedStatement.executeQuery();
            //执行查询操作
            ResultSet rs = preparedStatement.executeQuery();
            
            while(rs.next()) {
                System.out.println(rs.getInt("id") + "	"
                        + rs.getString("name") + "	" + rs.getBoolean("gender") 
                        + "	" + rs.getDate("birthday"));
             }
        }

    6.3 ResultSetMetaData 结果集元数据

    通过 ResultSet.getMetaData();获取 ,主要对于表中的一些列进行获取,处理

    Connection conn = JdbcUtils.getConnection();
            
            String sql="SELECT * FROM STUDENT WHERE id=?";
            PreparedStatement pStatement = conn.prepareStatement(sql);
            
            pStatement.setInt(1, 1);
            ResultSet reSet = pStatement.executeQuery();
            
            ResultSetMetaData metaData = reSet.getMetaData();
            
            int count = metaData.getColumnCount();
            
            for (int i = 1; i <= count; i++) {
                String columnClassName = metaData.getColumnClassName(i);//类型
                String columnName = metaData.getColumnName(i);//列名
                int columnType = metaData.getColumnType(i);//列属性值
                String typeName = metaData.getColumnTypeName(i);//列类型名
                String label = metaData.getColumnLabel(i);//列名
                System.out.println(columnClassName+"	"+columnName+"	"+columnType+"	"+typeName+"	"+label);
            }
  • 相关阅读:
    .vue文件在phpstorm中红线解决办法
    javascript预编译详解
    javascript数据类型判断及数据隐式和显示转换
    用git版本库工具上传项目到github(新手简单易上手)
    javascript的数据运算和条件判断
    javascript基础类型和引用类型
    uniapp开发钉钉小程序遇到的坑!!!
    pdf解析器 用于小程序 h5
    百度的Ueditor(php)上传到aws s3存储方案
    css3 pointer-event属性
  • 原文地址:https://www.cnblogs.com/dgwblog/p/11797616.html
Copyright © 2020-2023  润新知