1.PrepareStatement接口继承了Statement接口

2.PrepareStatement可以防止SQL注入

3.PrepareStatement执行效率高于Statement

原因在于PrepareStatement可以执行多次

PreparedStatement preparedStatement = connection.prepareStatement(sql);

使用

preparedStatement.executeUpdate();执行多次

比如说

String sql="update emp set ename=? where eid=?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, "tang1seng");
preparedStatement.setString(2, "1");
preparedStatement.executeUpdate();//如果没有手动开启事务,该sql已经执行
preparedStatement.setString(1, "tangseng");
preparedStatement.setString(2, "2");
preparedStatement.executeUpdate();

Statement对象用于执行一条静态的SQL语句。每次执行SQL语句时,都需要使用executeQuery(sql)executeUpdate(sql)等方法来执行单个SQL语句。如果您想执行多条SQL语句,需要将它们分别作为独立的Statement执行。

Statement statement = connection.createStatement();
statement.executeUpdate("update emp set ename='3333' where eid=1");//没有手动开启事务,默认数据库已经执行
statement.executeUpdate("update emp set ename='3333' where eid=2");

一般很少用preparedStatement.executeUpdate(String sql);方法,如果用了该方法,其实和statement是一样的

一般不会在PreparedStatement中使用executeUpdate(sql)这种形式的方法,因为它与使用Statement的方式类似,无法充分利用PreparedStatement的预编译和参数绑定的优势。

PreparedStatement对象的主要优势在于它的预编译功能和参数绑定功能,可以提高执行效率和安全性。通过预编译SQL语句,并使用占位符(?)表示参数,可以避免SQL注入等安全问题。而且,由于预编译的语句已经被数据库解析和优化过,可以在多次执行时提供更好的性能。

如果使用preparedStatement.executeUpdate(sql)这种形式,就相当于放弃了预编译和参数绑定的优势,变成了类似于Statement的方式,只能执行一次。这样就无法充分发挥PreparedStatement的潜力。

因此,通常情况下,我们会使用PreparedStatement的预编译和参数绑定功能,通过调用executeUpdate()方法执行已经预编译好的SQL语句,而不是传递SQL语句作为参数。

关于Statement和PrepareStatement的批处理

将多条SQL语句,统一提交数据库服务器,提高效率

方法描述

1. void addBatch(String sql):将给定的SQL语句添加到此Statement对象的当前命令列表中(但并不执行),可以提高执行效率

2.void clearBatch():清空此Statement对象的当前SQL命令列表

int[] excuteBatch():将一批命令提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组

演示Statement批处理

public class Demo07 {
    public static void main(String[] args) {
        String sql1="insert into emp values(13,'小王','男',4000,'2022-02-02','财务部')";
        String sql2="insert into emp values(14,'小红','女',5000,'2022-03-03','财务部')";
        String sql3="insert into emp values(15,'小丽','女',6000,'2022-04-04','财务部')";

        try( Connection connection = DBUtils.getConnection();){
            /**
             * 通信开销:在使用Statement的方式中,每次调用executeUpdate()方法都会将SQL语句发送到数据库执行,
             * 并等待结果返回后再执行下一条语句。这会产生多次与数据库的通信开销,可能会降低执行效率。
             * 而批处理允许将多个SQL语句一次性发送到数据库执行,从而减少通信开销,提高效率。
             *
             * 事务处理:使用Statement的方式,默认情况下每个executeUpdate()方法调用都是一个独立的事务,
             * 即每次执行都是自动提交的(autocommit)。而在批处理中,可以将多个SQL语句作为一个事务进行批量处理,
             * 并通过设置Connection对象的自动提交模式来控制是否使用事务。
             *
             * 错误处理:在使用Statement的方式时,如果某个executeUpdate()方法调用执行失败,会立即抛出异常,
             * 并终止执行后续的语句。而在批处理中,可以通过调用executeBatch()方法一次性执行批量操作,并返回每个语句执行的结果,
             * 可以根据返回结果进行错误处理。
             *
             * SQL注入风险:使用Statement的方式,需要将具体的SQL语句作为字符串传递给executeUpdate()方法,
             * 存在SQL注入的风险。而批处理中可以使用PreparedStatement对象和参数绑定,从而避免SQL注入问题。
              */
              Statement statement=connection.createStatement();
//            statement.executeUpdate(sql1);
//            statement.executeUpdate(sql2);
//            statement.executeUpdate(sql3);
            //添加批量操作,并不会执行
            statement.addBatch(sql1);
            statement.addBatch(sql2);
            statement.addBatch(sql3);
            //执行
            statement.executeBatch();

        } catch (SQLException e) {
            e.printStackTrace();
        }


    }
}

PropareStatement的批处理演示

public class Demo08 {

    public static void main(String[] args) {
        String sql="insert into emp values(?,?,'男',4000,'2022-02-02','财务部')";



        try(Connection connection = DBUtils.getConnection();){

            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, "117");
            preparedStatement.setString(2, "哈哈");
            preparedStatement.addBatch();
            preparedStatement.setString(1, "118");
            preparedStatement.setString(2, "呵呵");
            preparedStatement.addBatch();

            preparedStatement.executeBatch();


            //某些特定逻辑或for循环里
            //在for循环外面  还可以执行preparedStatement.executeBatch();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

有时候批处理时候可能在一个for循环,或某些特定逻辑里面

其实在最后还可以执行一次

preparedStatement.executeBatch();

PreparedStatement的批处理(batch processing)和使用多次executeUpdate()的方式有一些区别。

  1. 执行方式:使用多次executeUpdate()方式是一次执行一条SQL语句,然后等待结果返回后再执行下一条语句。而使用批处理,可以一次性将多个SQL语句发送到数据库执行,从而减少与数据库之间的通信次数,提高执行效率。

  2. 事务处理:使用多次executeUpdate()的方式,每条语句都会被视为一个独立的事务,即每次执行都是自动提交的(autocommit)。而在批处理中,可以将多个SQL语句作为一个事务进行批量处理,可以通过设置Connection对象的自动提交模式来控制是否使用事务。

  3. 数据库支持:使用多次executeUpdate()方式是标准的JDBC操作,在所有支持JDBC的数据库中都可用。而批处理的支持因数据库而异,不是所有的数据库都完全支持批处理操作。可以通过调用DatabaseMetaData对象的supportsBatchUpdates()方法来检查数据库是否支持批处理操作。

  4. 错误处理:在使用多次executeUpdate()的方式时,如果某个语句执行失败,会立即抛出异常,并终止执行后续的语句。而在批处理中,可以通过调用executeBatch()方法来一次性执行批量操作,并返回每个语句执行的结果,可以根据返回结果进行错误处理。

总结而言,使用多次executeUpdate()的方式适用于需要分别处理每条SQL语句结果的场景,并且每条语句都是一个独立的事务。而批处理适用于一次性执行多个SQL语句,并进行批量操作和事务处理的场景,以提高执行效率。需要根据具体的业务需求和数据库支持情况来选择合适的方式。

05-30 06:15