• JDBC的Statement对象


    以下内容引用自http://wiki.jikexueyuan.com/project/jdbc/statements.html

    一旦获得了数据库的连接,就可以和数据库进行交互。JDBC的Statement,CallableStatement和PreparedStatement接口定义的方法和属性,可以发送SQL命令或PL/SQL命令到数据库,并从数据库接收数据。

    在数据库中,它们还定义了帮助Java和SQL数据类型之间转换数据差异的方法。

    下表提供了每个接口的用途概要,根据实际目的决定使用哪个接口。

    接口推荐使用
    Statement 可以正常访问数据库,适用于运行静态SQL语句。 Statement接口不接受参数。
    PreparedStatement 计划多次使用SQL语句, PreparedStatement接口运行时接受输入的参数。
    CallableStatement 适用于当要访问数据库存储过程的时候, CallableStatement接口运行时也接受输入的参数。

    一、Statement对象

    1、创建Statement对象

    在准备使用Statement对象执行SQL语句之前,需要使用Connection对象的createStatement()方法创建一个,如下面的示例所示:

    Statement stmt = null;
    try {
       stmt = conn.createStatement( );
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       . . .
    }

    当创建了一个Statement对象之后,可以用它的三个执行方法的任一方法来执行SQL语句。

    • boolean execute(String SQL) : 如果ResultSet对象可以被检索,则返回的布尔值为true,否则返回false 。当需要使用真正的动态SQL时,可以使用这个方法来执行SQL DDL语句。

    • int executeUpdate(String SQL) : 返回执行SQL语句影响的行的数目。使用该方法来执行SQL语句,是希望得到一些受影响的行的数目,例如,INSERT,UPDATE或DELETE语句。

    • ResultSet executeQuery(String SQL) : 返回一个ResultSet对象。当希望得到一个结果集时使用该方法,就像使用一个SELECT语句。

    2、关闭Statement对象

    正如关闭一个Connection对象来节约数据库资源,出于同样的原因也应该关闭Statement对象。

    简单的调用close()方法就可以完成这项工作。如果关闭了Connection对象,那么它也会关闭Statement对象。然而,应该始终明确关闭Statement对象,以确保真正的清除。

    Statement stmt = null;
    try {
       stmt = conn.createStatement( );
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       stmt.close();
    }

    示例:

    //STEP 1. Import required packages
    import java.sql.*;
    
    public class FirstExample {
        // JDBC driver name and database URL
        static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        static final String DB_URL = "jdbc:mysql://localhost/Test?serverTimezone=UTC";
    
        // Database credentials
        static final String USER = "root";
        static final String PASS = "root";
    
        public static void main(String[] args) {
            Connection conn = null;
            Statement stmt = null;
            try {
                // STEP 2: Register JDBC driver
                Class.forName("com.mysql.jdbc.Driver");
    
                // STEP 3: Open a connection
                System.out.println("Connecting to database...");
                conn = DriverManager.getConnection(DB_URL, USER, PASS);
    
                // STEP 4: Execute a query
                System.out.println("Creating statement...");
                stmt = conn.createStatement();
                String sql;
                sql = "SELECT id, first, last, age FROM Employees";
                ResultSet rs = stmt.executeQuery(sql);
    
                // STEP 5: Extract data from result set
                while (rs.next()) {
                    // Retrieve by column name
                    int id = rs.getInt("id");
                    int age = rs.getInt("age");
                    String first = rs.getString("first");
                    String last = rs.getString("last");
    
                    // Display values
                    System.out.print("ID: " + id);
                    System.out.print(", Age: " + age);
                    System.out.print(", First: " + first);
                    System.out.println(", Last: " + last);
                }
                // STEP 6: Clean-up environment
                rs.close();
                stmt.close();
                conn.close();
            } catch (SQLException se) {
                // Handle errors for JDBC
                se.printStackTrace();
            } catch (Exception e) {
                // Handle errors for Class.forName
                e.printStackTrace();
            } finally {
                // finally block used to close resources
                try {
                    if (stmt != null)
                        stmt.close();
                } catch (SQLException se2) {
                } // nothing we can do
                try {
                    if (conn != null)
                        conn.close();
                } catch (SQLException se) {
                    se.printStackTrace();
                } // end finally try
            } // end try
            System.out.println("Goodbye!");
        }// end main
    }// end FirstExample

    这将产生如下所示结果:

    二、PreparedStatement对象

    PreparedStatement接口扩展了Statement接口,它用一个常用的Statement对象增加几个高级功能。

    这个Statement对象可以提供灵活多变的动态参数。

    1、创建PreparedStatement对象

    PreparedStatement pstmt = null;
    try {
       String SQL = "Update Employees SET age = ? WHERE id = ?";
       pstmt = conn.prepareStatement(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       . . .
    }

    JDBC中所有的参数都被用?符号表示,这是已知的参数标记。在执行SQL语句之前,必须赋予每一个参数确切的数值。

    setXXX()方法将值绑定到参数,其中XXX表示希望绑定到输入参数的Java数据类型。如果忘了赋予值,将收到一个SQLException。

    每个参数标记映射它的序号位置。第一标记表示位置1,下一个位置为2等等。这种方法不同于Java数组索引,它是从0开始的。

    所有的Statement对象的方法都与数据库交互,(a)execute(),(b)executeQuery(),及(c)executeUpdate()也能被PreparedStatement对象引用。然而,这些方法被SQL语句修改后是可以输入参数的。

    2、关闭PreparedStatement对象

    正如关闭一个Statement对象,出于同样的原因,也应该关闭PreparedStatement对象。

    简单的调用close()方法可以完成这项工作。如果关闭了Connection对象,那么它也会关闭PreparedStatement对象。然而,应该始终明确关闭PreparedStatement对象,以确保真正的清除。

    PreparedStatement pstmt = null;
    try {
       String SQL = "Update Employees SET age = ? WHERE id = ?";
       pstmt = conn.prepareStatement(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       pstmt.close();
    }

    示例:

    //STEP 1. Import required packages
    import java.sql.*;
    
    public class JDBCExample {
        // JDBC driver name and database URL
        static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        static final String DB_URL = "jdbc:mysql://localhost/Test?serverTimezone=UTC";
    
        // Database credentials
        static final String USER = "root";
        static final String PASS = "root";
    
        public static void main(String[] args) {
            Connection conn = null;
            PreparedStatement stmt = null;
            try {
                // STEP 2: Register JDBC driver
                Class.forName("com.mysql.jdbc.Driver");
    
                // STEP 3: Open a connection
                System.out.println("Connecting to database...");
                conn = DriverManager.getConnection(DB_URL, USER, PASS);
    
                // STEP 4: Execute a query
                System.out.println("Creating statement...");
                String sql = "UPDATE Employees set age=? WHERE id=?";
                stmt = conn.prepareStatement(sql);
    
                // Bind values into the parameters.
                stmt.setInt(1, 35); // This would set age
                stmt.setInt(2, 102); // This would set ID
    
                // Let us update age of the record with ID = 102;
                int rows = stmt.executeUpdate();
                System.out.println("Rows impacted : " + rows);
    
                // Let us select all the records and display them.
                sql = "SELECT id, first, last, age FROM Employees";
                ResultSet rs = stmt.executeQuery(sql);
    
                // STEP 5: Extract data from result set
                while (rs.next()) {
                    // Retrieve by column name
                    int id = rs.getInt("id");
                    int age = rs.getInt("age");
                    String first = rs.getString("first");
                    String last = rs.getString("last");
    
                    // Display values
                    System.out.print("ID: " + id);
                    System.out.print(", Age: " + age);
                    System.out.print(", First: " + first);
                    System.out.println(", Last: " + last);
                }
                // STEP 6: Clean-up environment
                rs.close();
                stmt.close();
                conn.close();
            } catch (SQLException se) {
                // Handle errors for JDBC
                se.printStackTrace();
            } catch (Exception e) {
                // Handle errors for Class.forName
                e.printStackTrace();
            } finally {
                // finally block used to close resources
                try {
                    if (stmt != null)
                        stmt.close();
                } catch (SQLException se2) {
                } // nothing we can do
                try {
                    if (conn != null)
                        conn.close();
                } catch (SQLException se) {
                    se.printStackTrace();
                } // end finally try
            } // end try
            System.out.println("Goodbye!");
        }// end main
    }// end JDBCExample

    这将产生如下所示结果:

    三、CallableStatement对象

    正如一个Connection对象可以创建Statement对象和PreparedStatement对象,它也可以创建被用来执行调用数据库存储过程的CallableStatement对象。

    1、创建CallableStatement对象

    假如需要执行以下的Oracle存储过程:

    CREATE OR REPLACE PROCEDURE getEmpName 
       (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
    BEGIN
       SELECT first INTO EMP_FIRST
       FROM Employees
       WHERE ID = EMP_ID;
    END;

    注意:上面的存储过程已经写入到Oracle数据库中,但正在使用MySQL数据库,那么可以在MySQL的EMP数据库中创建相同的存储过程。

    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
    CREATE PROCEDURE `EMP`.`getEmpName` 
       (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
    BEGIN
       SELECT first INTO EMP_FIRST
       FROM Employees
       WHERE ID = EMP_ID;
    END $$
    
    DELIMITER ;

    三种类型的参数有:IN,OUT和INOUT。PreparedStatement对象只使用IN参数。CallableStatement对象可以使用所有的三个参数。

    这里是每个参数的定义:

    参数描述
    IN 在SQL语句创建的时候该参数是未知的。可以用setXXX()方法将值绑定到IN参数中。
    OUT 该参数由SQL语句的返回值提供。可以用getXXX()方法获取OUT参数的值。
    INOUT 该参数同时提供输入输出的值。可以用setXXX()方法将值绑定参数,并且用getXXX()方法获取值。

    下面的代码片段展示了基于存储过程如何使用Connection.prepareCall()方法来实例化CallableStatement对象。

    CallableStatement cstmt = null;
    try {
       String SQL = "{call getEmpName (?, ?)}";
       cstmt = conn.prepareCall(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       . . .
    }

    SQL的String变量使用参数占位符表示存储过程。

    使用CallableStatement对象就像使用PreparedStatement对象。必须在执行该语句之前将值绑定到所有的参数,否则将收到一个SQL异常。

    如果有IN参数,只要使用适用于PreparedStatement对象相同的规则和技巧;使用setXXX()方法绑定对应的Java数据类型。

    当使用OUT和INOUT参数时,就必须使用额外的CallableStatement方法-registerOutParameter()。 registerOutParameter()方法绑定JDBC数据类型,该数据是存储过程返回的值。

    一旦调用存储过程,可以用适当的getXXX()方法来获取OUT参数的值。这个方法将检索到的SQL类型映射成Java数据类型。

    2、关闭CallableStatement对象

    正如关闭其它的Statement对象,出于同样的原因,也应该关闭PreparedStatement对象。

    简单的调用close()方法可以完成这项工作。如果关闭了Connection对象,那么它也会关闭CallableStatement对象。然而,应该始终明确关闭CallableStatement对象,以确保真正的清除。

    CallableStatement cstmt = null;
    try {
       String SQL = "{call getEmpName (?, ?)}";
       cstmt = conn.prepareCall(SQL);
       . . .
    }
    catch (SQLException e) {
       . . .
    }
    finally {
       cstmt.close();
    }

    示例:

    创建存储过程:

    DELIMITER $$
    
    DROP PROCEDURE IF EXISTS `Test`.`getEmpName` $$
    CREATE PROCEDURE `Test`.`getEmpName` 
       (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
    BEGIN
       SELECT first INTO EMP_FIRST
       FROM Employees
       WHERE ID = EMP_ID;
    END $$
    
    DELIMITER ;

    代码:

    //STEP 1. Import required packages
    import java.sql.*;
    
    public class JDBCExample2 {
        // JDBC driver name and database URL
        static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
        static final String DB_URL = "jdbc:mysql://localhost/Test?serverTimezone=UTC";
    
        // Database credentials
        static final String USER = "root";
        static final String PASS = "root";
    
        public static void main(String[] args) {
            Connection conn = null;
            CallableStatement stmt = null;
            try {
                // STEP 2: Register JDBC driver
                Class.forName("com.mysql.jdbc.Driver");
    
                // STEP 3: Open a connection
                System.out.println("Connecting to database...");
                conn = DriverManager.getConnection(DB_URL, USER, PASS);
    
                // STEP 4: Execute a query
                System.out.println("Creating statement...");
                String sql = "{call getEmpName (?, ?)}";
                stmt = conn.prepareCall(sql);
    
                // Bind IN parameter first, then bind OUT parameter
                int empID = 102;
                stmt.setInt(1, empID); // This would set ID as 102
                // Because second parameter is OUT so register it
                stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
    
                // Use execute method to run stored procedure.
                System.out.println("Executing stored procedure...");
                stmt.execute();
    
                // Retrieve employee name with getXXX method
                String empName = stmt.getString(2);
                System.out.println("Emp Name with ID:" + empID + " is " + empName);
                stmt.close();
                conn.close();
            } catch (SQLException se) {
                // Handle errors for JDBC
                se.printStackTrace();
            } catch (Exception e) {
                // Handle errors for Class.forName
                e.printStackTrace();
            } finally {
                // finally block used to close resources
                try {
                    if (stmt != null)
                        stmt.close();
                } catch (SQLException se2) {
                } // nothing we can do
                try {
                    if (conn != null)
                        conn.close();
                } catch (SQLException se) {
                    se.printStackTrace();
                } // end finally try
            } // end try
            System.out.println("Goodbye!");
        }// end main
    }// end JDBCExample

    这将产生如下所示结果:

    测试工程:https://github.com/easonjim/5_java_example/tree/master/jdbcbasics/test3

  • 相关阅读:
    vue 同页面不同参数
    vue的data用到this问题
    vue轮播,不是只有左右切换的,还有只切换src的
    vue页面高度填充,不出现滚动条
    WdatePicker做出onchange效果
    总结最近移动端遇到的坑(auto-size + zepto)
    react
    ES6-set && 数组剔重
    [置顶] Jquery easyui+Jsonp+asp.net+翻页 事件版
    扩展Jquery easyui的validator插件
  • 原文地址:https://www.cnblogs.com/EasonJim/p/6994014.html
Copyright © 2020-2023  润新知