JDBC进阶 元数据

Posted --- 锅老官扎起哦!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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);
        }

 

 

以上是关于JDBC进阶 元数据的主要内容,如果未能解决你的问题,请参考以下文章

JDBC学习笔记——利用反射及JDBC元数据编写通用的查询方法

从 jdbc/postgresql 获取新创建表的列元数据

用JDBC获得元数据

JDBC------之结果集元数据的操作02

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情

Java进阶一篇文让你知道JDBC 和MySQL的增删改查