Statement详解

发布时间 2023-04-03 08:45:21作者: 围观的小妖g

Statement接口

Statement接口及它的子接口PreparedStatement和CallableStatement。

Statement接口中定义了执行SQL语句的方法,这些方法不支持参数输入,

PreparedStatement接口中增加了设置SQL参数的方法,

CallableStatement接口继承自PreparedStatement,在此基础上增加了调用存储过程以及检索存储过程调用结果的方法。

  • 创建
@Test
  public void statementTest() throws SQLException {
    Connection connection = DriverManager.getConnection("jdbc:mysql://xxxx:3306/demo",
      "xxxx",
      "xxxx");

    //简单创建
    Statement statement = connection.createStatement();

    //重载方法
    /**
     * resultSetType – one of the following ResultSet constants:
     *                  ResultSet.TYPE_FORWARD_ONLY : 表示ResultSet对象类型的常量,该对象的光标只能向前移动。
     *                  ResultSet.TYPE_SCROLL_INSENSITIVE, : 表示ResultSet对象的类型的常量,该对象是可滚动的,但通常对ResultSet基础数据的更改不敏感。
     *                  or ResultSet.TYPE_SCROLL_SENSITIVE : 表示ResultSet对象的类型的常量,该对象是可滚动的,通常对ResultSet基础数据的更改敏感。
     * resultSetConcurrency – one of the following ResultSet constants:
     *                  ResultSet.CONCUR_READ_ONLY: 表示不能更新的ResultSet对象的并发模式的常量。
     *                  or ResultSet.CONCUR_UPDATABLE: 指示可更新的ResultSet对象的并发模式的常量。
     * resultSetHoldability – one of the following ResultSet constants:
     *                  ResultSet.HOLD_CURSORS_OVER_COMMIT: 表示具有此可保持性的打开的ResultSet对象在提交当前事务时将保持打开的常量。
     *                  or ResultSet.CLOSE_CURSORS_AT_COMMIT: 指示具有此可保持性的打开ResultSet对象的常量将在提交当前事务时关闭。
     */
    Statement statement1 = connection.createStatement(
      ResultSet.TYPE_SCROLL_INSENSITIVE,
      ResultSet.CONCUR_UPDATABLE,
      ResultSet.HOLD_CURSORS_OVER_COMMIT);

    //重载方法
    /**
     * resultSetType – one of the following ResultSet constants:
     *                  ResultSet.TYPE_FORWARD_ONLY : 表示ResultSet对象类型的常量,该对象的光标只能向前移动。
     *                  ResultSet.TYPE_SCROLL_INSENSITIVE, : 表示ResultSet对象的类型的常量,该对象是可滚动的,但通常对ResultSet基础数据的更改不敏感。
     *                  or ResultSet.TYPE_SCROLL_SENSITIVE : 表示ResultSet对象的类型的常量,该对象是可滚动的,通常对ResultSet基础数据的更改敏感。
     * resultSetConcurrency – one of the following ResultSet constants:
     *                  ResultSet.CONCUR_READ_ONLY: 表示不能更新的ResultSet对象的并发模式的常量。
     *                  or ResultSet.CONCUR_UPDATABLE: 指示可更新的ResultSet对象的并发模式的常量。
     */
    Statement statement2 = connection.createStatement(
      ResultSet.TYPE_SCROLL_INSENSITIVE,
      ResultSet.HOLD_CURSORS_OVER_COMMIT);

  }

Statement的主要作用是与数据库进行交互,该接口中定义了一些数据库操作以及检索SQL执行结果相关的方法,具体如下:

在这里插入图片描述

注意:

  • 如果数据库支持返回的更新数量大于Integer.MAX_VALUE,则需要调用executeLargeUpdate()方法。
  • 当数据库支持返回影响的行数大于Integer.MAX_VALUE时,需要使用getLargeUpdateCount()方法。

PreparedStatement

PreparedStatement接口继承自Statement接口,在Statement接口的基础上增加了参数占位符功能。PreparedStatement接口中增加了一些方法,可以为占位符设置值。PreparedStatement的实例表示可以被预编译的SQL语句,执行一次后,后续多次执行时效率会比较高。使用PreparedStatement实例执行SQL语句时,可以使用“?”作为参数占位符,然后使用PreparedStatement接口中提供的方法为占位符设置参数值。

  • 创建
@Test
  public void preparedStatementTest() throws SQLException {
    Connection connection = DriverManager.getConnection("jdbc:mysql://xxxx:3306/demo",
      "xxxx",
      "xxxx");

    PreparedStatement preparedStatement = connection.prepareStatement("select * from demo where id = ?");

    //重载
    /**
     * sql – a String object that is the SQL statement to be sent to the database; may contain one or more '?' IN parameters
     * resultSetType – a result set type; one of
     *                 ResultSet.TYPE_FORWARD_ONLY, : 表示ResultSet对象类型的常量,该对象的光标只能向前移动。
     *                 ResultSet.TYPE_SCROLL_INSENSITIVE, or : 表示ResultSet对象的类型的常量,该对象是可滚动的,但通常对ResultSet基础数据的更改不敏感。
     *                 ResultSet.TYPE_SCROLL_SENSITIVE: 表示ResultSet对象的类型的常量,该对象是可滚动的,通常对ResultSet基础数据的更改敏感。
     * resultSetConcurrency – a concurrency type; one of
     *                 ResultSet.CONCUR_READ_ONLY or : 表示不能更新的ResultSet对象的并发模式的常量。
     *                 ResultSet.CONCUR_UPDATABLE: 指示可更新的ResultSet对象的并发模式的常量。
     */
    PreparedStatement preparedStatement1 = connection.prepareStatement("select * from demo where id = ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);

    //重载方法
    /**
     * sql – a String object that is the SQL statement to be sent to the database; may contain one or more '?' IN parameters
     * resultSetType – a result set type; one of
     *                 ResultSet.TYPE_FORWARD_ONLY, : 表示ResultSet对象类型的常量,该对象的光标只能向前移动。
     *                 ResultSet.TYPE_SCROLL_INSENSITIVE, or : 表示ResultSet对象的类型的常量,该对象是可滚动的,但通常对ResultSet基础数据的更改不敏感。
     *                 ResultSet.TYPE_SCROLL_SENSITIVE: 表示ResultSet对象的类型的常量,该对象是可滚动的,通常对ResultSet基础数据的更改敏感。
     * resultSetConcurrency – a concurrency type; one of
     *                 ResultSet.CONCUR_READ_ONLY or : 表示不能更新的ResultSet对象的并发模式的常量。
     *                 ResultSet.CONCUR_UPDATABLE: 指示可更新的ResultSet对象的并发模式的常量。
     * resultSetHoldability – one of the following ResultSet constants:
     *                ResultSet.HOLD_CURSORS_OVER_COMMIT or : 表示具有此可保持性的打开的ResultSet对象在提交当前事务时将保持打开的常量。
     *                ResultSet.CLOSE_CURSORS_AT_COMMIT: 指示具有此可保持性的打开ResultSet对象的常量将在提交当前事务时关闭。
     */
    PreparedStatement preparedStatement2 = connection.prepareStatement("select * from demo where id = ?", ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);


    //重载方法
    /**
     * sql – an SQL statement that may contain one or more '?' IN parameter placeholders
     * columnIndexes – 列索引数组,指示应从插入的行返回的列
     */
    PreparedStatement preparedStatement3 = connection.prepareStatement("select * from demo where id = ?", new int[]{1, 2});

    //重载方法
    /**
     * sql – an SQL statement that may contain one or more '?' IN parameter placeholders
     * columnNames – 列名数组,指示应从插入的行返回的列
     */
    PreparedStatement preparedStatement4 = connection.prepareStatement("select * from demo where id = ?", new String[]{"select * from demo where id = ?"});

    //重载方法
    /**
     * sql – an SQL statement that may contain one or more '?' IN parameter placeholders
     * autoGeneratedKeys – a flag indicating whether auto-generated keys should be returned; one of
     *                     Statement.RETURN_GENERATED_KEYS or : 指示生成的键应可供检索的常量。
     *                     Statement.NO_GENERATED_KEYS: 指示生成的键不应供检索的常量。
     */
    PreparedStatement preparedStatement5 = connection.prepareStatement("select * from demo where id = ?", Statement.NO_GENERATED_KEYS);

  }
  • 使用示例
    在这里插入图片描述
    需要注意的是,在使用PreparedStatement对象执行SQL语句之前必须为每个参数占位符设置对应的值,否则调用executeQuery()、executeUpdate()或execute()等方法时会抛出SQLException异常。PreparedStatement对象设置的参数在执行后不能被重置,需要显式地调用clearParameters()方法清除先前设置的值,再为参数重新设置值即可。

对于一个给定的Statement对象,在execute()、executeQuery()、executeUpdate()、executeBatch()或clearParameters()方法调用之前,如果占位符已经使用setXXX()方法设置值,应用程序不可以再次调用setXXX()方法修改已经设置的值。但是应用程序可以在execute()、executeQuery()、executeUpdate()、executeBatch()或clearParameters()方法调用后,再次调用setXXX()方法覆盖先前设置的值。不遵循这一约束可能会导致不可预知的结果。

我们在使用setXXX()方法为参数占位符设置值时存在一个数据转换过程。setXXX()方法的参数为Java数据类型,需要转换为JDBC类型(java.sql.Types中定义的SQL类型),这一过程由JDBC驱动来完成。Java类型与JDBC类型之间的对应关系如表2-2所示。

在这里插入图片描述
PreparedStatement接口中提供了一个setObject()方法,可以将Java类型转换为JDBC类型。该方法可以接收三个参数,第一个参数为占位符位置,第二个参数为Java对象,第三个参数是要转换成的JDBC类型。如果Java对象与JDBC类型不兼容,就会抛出SQLException异常。

PreparedStatement接口中提供了一个setNull()方法,可以将占位符参数设置为JDBC的NULL。该方法接收两个参数,第一个参数为占位符的位置,第二个参数为JDBC类型。该方法的语法格式如下:
在这里插入图片描述
JDBC API中提供了一个ParameterMetaData接口,用于描述PreparedStatement对象的参数信息,包括参数个数、参数类型等。PreparedStatement接口中提供了一个getParameterMetaData()方法,用于获取ParameterMetaData实例

CallableStatement

CallableStatement接口继承自PreparedStatement接口,在PreparedStatement的基础上增加了调用存储过程并检索调用结果的功能。
在这里插入图片描述
CallableStatement对象可以使用3种类型的参数:IN、OUT和INOUT。可以将参数指定为序数参数或命名参数,必须为IN或INOUT参数的每个参数占位符设置一个值,必须为OUT或INOUT参数中的每个参数占位符调用registerOutParameter()方法。存储过程参数的数量、类型和属性可以使用DatabaseMetaData接口提供的getProcedureColumns()方法获取。需要注意的是,使用setXXX()方法为参数占位符设置值时,下标必须从1开始。语句中的字面量参数值不会增加参数占位符的序数值.

注意: 使用Statement对象执行完SQL后也需要关闭。Statement接口中提供了close()方法,用于关闭Statement对象;另外还提供了isClosed()方法,用于判断该Statement对象是否关闭。

注意:摘要于《mybatis3源码深度解析》