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()
的方式有一些区别。
-
执行方式:使用多次
executeUpdate()
方式是一次执行一条SQL语句,然后等待结果返回后再执行下一条语句。而使用批处理,可以一次性将多个SQL语句发送到数据库执行,从而减少与数据库之间的通信次数,提高执行效率。 -
事务处理:使用多次
executeUpdate()
的方式,每条语句都会被视为一个独立的事务,即每次执行都是自动提交的(autocommit)。而在批处理中,可以将多个SQL语句作为一个事务进行批量处理,可以通过设置Connection
对象的自动提交模式来控制是否使用事务。 -
数据库支持:使用多次
executeUpdate()
方式是标准的JDBC操作,在所有支持JDBC的数据库中都可用。而批处理的支持因数据库而异,不是所有的数据库都完全支持批处理操作。可以通过调用DatabaseMetaData
对象的supportsBatchUpdates()
方法来检查数据库是否支持批处理操作。 -
错误处理:在使用多次
executeUpdate()
的方式时,如果某个语句执行失败,会立即抛出异常,并终止执行后续的语句。而在批处理中,可以通过调用executeBatch()
方法来一次性执行批量操作,并返回每个语句执行的结果,可以根据返回结果进行错误处理。
总结而言,使用多次executeUpdate()
的方式适用于需要分别处理每条SQL语句结果的场景,并且每条语句都是一个独立的事务。而批处理适用于一次性执行多个SQL语句,并进行批量操作和事务处理的场景,以提高执行效率。需要根据具体的业务需求和数据库支持情况来选择合适的方式。