preparedStatement.executeUpdate()的作用
-
定义和基本用途
PreparedStatement.executeUpdate()
是Java中用于执行SQL数据操作语言(DML)语句(如INSERT
、UPDATE
、DELETE
)或数据定义语言(DDL)语句(如CREATE TABLE
、ALTER TABLE
等)的方法。它会将SQL语句发送到数据库进行执行,并返回一个整数,表示受该语句影响的行数。
-
对于插入(INSERT)操作
- 示例场景:假设你正在构建一个用户注册系统,当用户提交注册信息后,需要将用户数据插入到数据库的
users
表中。 - 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class UserRegistration { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; try (Connection connection = DriverManager.getConnection(url, username, password)) { String insertQuery = "INSERT INTO users (name, email, password) VALUES (?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(insertQuery); preparedStatement.setString(1, "John Doe"); preparedStatement.setString(2, "johndoe@example.com"); preparedStatement.setString(3, "hashed_password"); int rowsAffected = preparedStatement.executeUpdate(); if (rowsAffected > 0) { System.out.println("User inserted successfully."); } else { System.out.println("Insertion failed."); } } catch (SQLException e) { e.printStackTrace(); } } }
- 在这个例子中,
executeUpdate()
方法将INSERT
语句发送到数据库执行。如果插入成功,受影响的行数(在这里是1行,因为插入了一个新用户)会大于0,程序会打印出“User inserted successfully.”。
- 示例场景:假设你正在构建一个用户注册系统,当用户提交注册信息后,需要将用户数据插入到数据库的
-
对于更新(UPDATE)操作
- 示例场景:考虑一个电商系统,需要更新商品的价格。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class UpdateProductPrice { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; try (Connection connection = DriverManager.getConnection(url, username, password)) { String updateQuery = "UPDATE products SET price =? WHERE product_id =?"; PreparedStatement preparedStatement = connection.prepareStatement(updateQuery); preparedStatement.setDouble(1, 19.99); preparedStatement.setInt(2, 12345); int rowsAffected = preparedStatement.executeUpdate(); if (rowsAffected > 0) { System.out.println("Product price updated successfully."); } else { System.out.println("Update failed."); } } catch (SQLException e) { e.printStackTrace(); } } }
- 这里,
executeUpdate()
执行UPDATE
语句,尝试更新product_id
为12345的商品价格。如果有符合条件的商品并且价格被成功更新,受影响的行数会大于0,程序会打印出相应的成功消息。
-
对于删除(DELETE)操作
- 示例场景:在一个内容管理系统中,需要删除指定的文章。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class DeleteArticle { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; try (Connection connection = DriverManager.getConnection(url, username, password)) { String deleteQuery = "DELETE FROM articles WHERE article_id =?"; PreparedStatement preparedStatement = connection.prepareStatement(deleteQuery); preparedStatement.setInt(1, 67890); int rowsAffected = preparedStatement.executeUpdate(); if (rowsAffected > 0) { System.out.println("Article deleted successfully."); } else { System.out.println("Deletion failed."); } } catch (SQLException e) { e.printStackTrace(); } } }
- 此示例中,
executeUpdate()
用于执行DELETE
语句来删除article_id
为67890的文章。根据受影响的行数,程序会输出相应的结果消息。
-
与DDL语句的使用(较少见但合法)
- 示例场景:在数据库初始化或架构调整时,可能需要创建新的表。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; public class CreateTable { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; try (Connection connection = DriverManager.getConnection(url, username, password)) { String createTableQuery = "CREATE TABLE new_table (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))"; PreparedStatement preparedStatement = connection.prepareStatement(createTableQuery); int result = preparedStatement.executeUpdate(); // 对于DDL语句,返回值在不同数据库可能有不同含义,通常0表示执行成功 if (result == 0) { System.out.println("Table created successfully."); } else { System.out.println("Table creation failed."); } } catch (SQLException e) { e.printStackTrace(); } } }
- 当使用
executeUpdate()
执行CREATE TABLE
这样的DDL语句时,返回值的意义可能因数据库而异。在某些数据库中,返回0可能表示语句执行成功,但这不是通用规则,具体要根据数据库的实现来判断。不过这种用法相对较少,因为通常更倾向于使用数据库管理工具或特定的数据库迁移框架来执行DDL操作。
preparedStatement.executeBatch()的作用
-
批量执行SQL语句的功能概述
PreparedStatement.executeBatch()
方法用于批量执行一组预编译的SQL语句。它将一批SQL语句发送到数据库进行一次性执行,而不是逐个发送和执行,这样可以显著提高性能,特别是在需要执行大量类似的SQL操作(如插入、更新或删除多条记录)时非常有用。
-
批量插入(INSERT)操作示例
- 场景描述:假设要将大量用户数据插入到数据库的用户表中。使用批量插入可以减少与数据库的交互次数,提高插入效率。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class BatchInsertUsers { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; List<User> userList = new ArrayList<>(); // 假设这里已经填充了用户数据列表,例如从文件读取或者其他数据源获取 userList.add(new User("John Doe", "johndoe@example.com", "password1")); userList.add(new User("Jane Smith", "janesmith@example.com", "password2")); try (Connection connection = DriverManager.getConnection(url, username, password)) { String insertQuery = "INSERT INTO users (name, email, password) VALUES (?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(insertQuery); for (User user : userList) { preparedStatement.setString(1, user.getName()); preparedStatement.setString(2, user.getEmail()); preparedStatement.setString(3, user.getPassword()); preparedStatement.addBatch(); } int[] results = preparedStatement.executeBatch(); int sum = 0; for (int result : results) { sum += result; } System.out.println("Total rows inserted: " + sum); } catch (SQLException e) { e.printStackTrace(); } } } class User { private String name; private String email; private String password; public User(String name, String email, String password) { this.name = name; this.email = email; this.password = password; } public String getName() { return name; } public String getEmail() { return email; } public String getPassword() { return password; } }
- 在这个例子中,首先创建了一个
PreparedStatement
用于插入用户数据。通过循环遍历用户列表,为每个用户设置参数并使用addBatch()
方法将SQL插入语句添加到批处理中。最后,使用executeBatch()
方法一次性将所有插入语句发送到数据库执行。返回的int[]
数组results
包含了每个SQL语句执行后影响的行数,通过累加这个数组中的元素可以得到总共插入的行数。
-
批量更新(UPDATE)操作示例
- 场景描述:考虑一个库存管理系统,需要批量更新多个商品的库存数量。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class BatchUpdateStock { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; List<StockUpdate> stockUpdateList = new ArrayList<>(); // 假设这里已经填充了库存更新数据列表,包含商品ID和新的库存数量 stockUpdateList.add(new StockUpdate(123, 10)); stockUpdateList.add(new StockUpdate(456, 20)); try (Connection connection = DriverManager.getConnection(url, username, password)) { String updateQuery = "UPDATE products SET stock_quantity =? WHERE product_id =?"; PreparedStatement preparedStatement = connection.prepareStatement(updateQuery); for (StockUpdate update : stockUpdateList) { preparedStatement.setInt(1, update.getNewStockQuantity()); preparedStatement.setInt(2, update.getProductId()); preparedStatement.addBatch(); } int[] results = preparedStatement.executeBatch(); int sum = 0; for (int result : results) { sum += result; } System.out.println("Total rows updated: " + sum); } catch (SQLException e) { e.printStackTrace(); } } } class StockUpdate { private int productId; private int newStockQuantity; public StockUpdate(int productId, int newStockQuantity) { this.productId = productId; this.newStockQuantity = newStockQuantity; } public int getProductId() { return productId; } public int getNewStockQuantity() { return newStockQuantity; } }
- 在这里,对于每个库存更新记录,设置
UPDATE
语句的参数并添加到批处理中。执行executeBatch()
后,同样通过处理返回的结果数组来统计总共更新的行数。
-
批量删除(DELETE)操作示例
- 场景描述:在一个内容管理系统中,需要批量删除过期的文章。
- 代码示例:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; public class BatchDeleteArticles { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/mydb"; String username = "root"; String password = "your_password"; List<Integer> articleIdList = new ArrayList<>(); // 假设这里已经填充了要删除的文章ID列表,例如从过期文章列表获取 articleIdList.add(789); articleIdList.add(1011); try (Connection connection = DriverManager.getConnection(url, username, password)) { String deleteQuery = "DELETE FROM articles WHERE article_id =?"; PreparedStatement preparedStatement = connection.prepareStatement(deleteQuery); for (Integer articleId : articleIdList) { preparedStatement.setInt(1, articleId); preparedStatement.addBatch(); } int[] results = preparedStatement.executeBatch(); int sum = 0; for (int result : results) { sum += result; } System.out.println("Total rows deleted: " + sum); } catch (SQLException e) { e.printStackTrace(); } } }
- 此示例中,对于每个要删除的文章ID,将相应的
DELETE
语句添加到批处理中,执行executeBatch()
后统计总共删除的行数。
-
返回值和异常处理注意事项
- 返回值含义:
executeBatch()
方法返回一个int[]
数组,其中每个元素对应批处理中的一个SQL语句执行后所影响的行数。对于不返回受影响行数的SQL语句(如某些数据库中的CREATE TABLE
等DDL语句),返回值的具体含义可能因数据库而异。 - 异常处理:当批处理中的任何一个SQL语句执行出错时,数据库可能会采取不同的行为。有些数据库可能会停止执行批处理中的后续语句并抛出异常,而有些数据库可能会继续执行其他语句并在
executeBatch()
方法返回的int[]
数组中用特殊值(如-2
在JDBC规范中用于表示执行失败但不影响后续语句执行)来标记出错的语句。因此,在使用executeBatch()
时,需要仔细考虑异常处理策略,以确保能够正确处理批处理执行过程中的错误。
- 返回值含义: