Oracle preparestatement中addBatch方法 抛异常的问题:不支持此特性

本文探讨了在Java中使用PreparedStatement的addBatch()方法时遇到的问题,并解释了该方法不接受参数的原因。同时介绍了如何正确地使用addBatch()方法进行批量SQL操作,以及使用Statement作为替代方案。

对于preparestatement.addBatch()方法使用报异常的地方原因是不能使用prepareStatement接口去实现addBatch()多个sql语句,addBatch()方法不接受参数的输入(即使传入的参数也无法执行,没有重写这个方法因此不支持),你可以查看一下官方文档API,大概意思是说:addBatch()只是使用适当的setXXX()方法将设置的绑定参数添加到批处理中,(对于CallbleStatement或OracleCallableStatement对象也是一样)

For prepared statements, update batching is used to batch multiple executions of the same statement with different sets of bind parameters. For a PreparedStatement or OraclePreparedStatement object, the addBatch() method takes no input–it simply adds the operation to the batch using the bind parameters last set by the appropriate setXXX() methods. (This is also true for CallableStatement or OracleCallableStatement objects, but remember that in the Oracle implementation of standard update batching, you will probably see no performance improvement in batching callable statements.)

For example (again assuming a Connection instance conn):


PreparedStatement pstmt =
conn.prepareStatement(“INSERT INTO employees VALUES(?, ?)”);

pstmt.setInt(1, 2000);
pstmt.setString(2, “Milo Mumford”);
pstmt.addBatch();

pstmt.setInt(1, 3000);
pstmt.setString(2, “Sulu Simpson”);
pstmt.addBatch();

At this point, two operations are in the batch.

Because a batch is associated with a single prepared statement object, you can batch only repeated executions of a single prepared statement, as in this example.

可以使用createStatement来实现这个功能,但性能就不好说了。。。。

Statement stmt = conn.createStatement();

stmt.addBatch(“INSERT INTO emp VALUES(1000, ‘Joe Jones’)”);
stmt.addBatch(“INSERT INTO dept VALUES(260, ‘Sales’)”);
stmt.addBatch(“INSERT INTO emp_dept VALUES(1000, 260)”);

<think>我们被要求回答关于Java中Statement和PreparedStatement的区别及使用场景的问题。根据提供的引用,我们可以整理出以下信息:1.**Statement**:-用于执行静态SQL语句,每次执行都需要编译。-示例:`Statementstmt=conn.createStatement();stmt.executeUpdate("UPDATECOFFEESSETSALES=75WHERECOF_NAMELIKE'Colombian'");`-如果多次执行相同的SQL语句(仅变量值不同),每次都需要重新编译,效率较低。-存在SQL注入风险,因为参数是直接拼接在SQL字符串中的。2.**PreparedStatement**:-是预编译的SQL语句,使用占位符(`?`)表示参数。-示例:`PreparedStatementpstmt=conn.prepareStatement("UPDATECOFFEESSETSALES=?WHERECOF_NAMELIKE?");pstmt.setInt(1,75);pstmt.setString(2,"Colombian");pstmt.executeUpdate();`-优势:-**性能提升**:预编译的SQL语句被缓存,当多次执行相同结构的SQL语句(仅参数不同)时,只需编译一次,后续执行更快。-**防止SQL注入**:通过参数化查询,用户输入被视为数据而非SQL代码,从而避免了SQL注入攻击。-**可读性和可维护性**:SQL语句与参数分离,便于修改。**主要区别总结**:-**编译与执行**:`Statement`每次执行都需要编译;`PreparedStatement`预编译,多次执行效率高。-**安全性**:`Statement`容易导致SQL注入;`PreparedStatement`能有效防止SQL注入。-**使用场景**:-`Statement`适用于执行一次性、不重复的静态SQL语句(如DDL语句:CREATE,ALTER,DROP)。-`PreparedStatement`适用于执行多次、结构相同但参数不同的SQL语句(如INSERT,UPDATE,DELETE等DML语句),尤其是在循环中执行批量操作时。**使用建议**:-在可能的情况下,优先使用`PreparedStatement`,因为它更安全且性能更好(特别是在多次执行时)。-对于简单的DDL操作,可以使用`Statement`。根据引用[2]和[3],我们可以知道PreparedStatement在多次执行相同结构的SQL时效率更高,并且可以防止SQL注入。因此,回答将围绕这些要点展开,并给出示例代码。</think>### Java 中 Statement 与 PreparedStatement 的区别及使用场景 #### 一、核心区别 1. **编译机制** - `Statement`:每次执行都需重新编译 SQL 语句,语法解析开销大[^2]。 - `PreparedStatement`:SQL 预编译后缓存在数据库,多次执行仅需替换参数值[^3]。 **性能影响**:高频操作时,`PreparedStatement` 速度优势显著(尤其循环执行相同结构 SQL)。 2. **安全性** - `Statement`:直接拼接参数值,存在 SQL 注入风险(如 `"WHERE name='" + input + "'"`)。 - `PreparedStatement`:参数化查询强制值/指令分离,用户输入视为纯数据而非代码[^3]。 **示例对比**: ```java // Statement (风险!) String sql = "SELECT * FROM users WHERE name='" + input + "'"; stmt.executeQuery(sql); // PreparedStatement (安全) PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE name=?"); pstmt.setString(1, input); // 自动转义特殊字符 ``` 3. **代码可维护性** - `PreparedStatement` 分离 SQL 结构与参数,修改更清晰: ```java // 修改参数无需重写SQL pstmt.setDouble(1, newPrice); pstmt.setString(2, "Colombian"); ``` #### 二、使用场景对比 | **场景** | **Statement** | **PreparedStatement** | |-------------------------|---------------------|--------------------------| | **执行次数** | 一次性操作(如 DDL)| 多次重复执行(如批量更新)| | **SQL 结构** | 静态 SQL(无参数) | 动态 SQL(含参数占位符) | | **安全性要求** | 内部可信环境 | 需防 SQL 注入的公开接口 | | **典型用例** | `CREATE TABLE`[^4] | 用户登录验证、订单处理 | #### 三、最佳实践建议 1. **优先选择 PreparedStatement**: 适用于 95% 的数据库操作,尤其涉及用户输入的场景(登录、搜索等)[^1]。 2. **Statement 的适用场景**: 执行数据库结构操作(如 `ALTER TABLE`)或确定无参数的静态 SQL。 3. **性能优化技巧**: - 批量操作时,使用 `PreparedStatement.addBatch()` 减少网络开销[^3]。 - 复用同一 `PreparedStatement` 对象避免重复编译。 > **关键结论**:`PreparedStatement` 通过预编译机制和参数化查询,在性能、安全性和代码可读性上全面优于 `Statement`,是现代 Java 数据库开发的首选[^1][^3]。 --- ### 相关问题 1. 如何在 Java 中使用 `PreparedStatement` 执行批量插入操作? 2. `PreparedStatement` 的预编译机制在不同数据库(如 MySQL/Oracle)中有何差异? 3. 除了防止 SQL 注入,`PreparedStatement` 还有哪些安全优势? 4. 什么情况下必须使用 `Statement` 而非 `PreparedStatement`?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值