
在开发基于java jdbc的数据库应用时,一个常见的需求是从数据库中查询多条记录并对它们进行逐一处理,例如批量发送邮件或生成报告。然而,如果数据访问层的设计不当,可能会导致即使数据库返回了多条记录,应用也只能处理其中的第一条。
原始代码示例中,getEmail方法旨在从USER表中查询多条用户的邮件地址:
// 原始查询语句
"SELECT EMAIL FROM USER WHERE USER.U_SEQ IN ('1','650')"这个查询显然会返回多条邮件地址。然而,原始的getEmail(ResultSet searchResultSet)私有方法在处理ResultSet后,最终只返回了result.get(0),即列表中的第一个UserDto对象。
private UserDto getEmail(ResultSet searchResultSet) throws SQLException {
List<UserDto > result = new ArrayList<UserDto >();
UserDto userDto = null;
while (searchResultSet.next()) {
userDto = new UserDto ();
userDto .setEmailAddress(searchResultSet.getString(1));
result.add(userDto );
}
// 问题所在:只返回了列表中的第一个对象
return result == null ? null : result.size() == 0 ? null : result.get(0);
}这导致在业务逻辑层调用delegate.getEmail()时,只能获取到第一个用户的邮件地址,后续的邮件发送操作也仅针对该地址执行,无法实现批量处理。
要解决上述问题,核心在于两点:
立即学习“Java免费学习笔记(深入)”;
首先,我们需要修改getEmail()方法及其辅助方法getEmail(ResultSet searchResultSet),使其能够返回一个List<UserDto>。
修改后的DAO层代码:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
// 假设 UserDto 和 getConnection() 方法已定义
// public class UserDto { private String emailAddress; public void setEmailAddress(String email) { this.emailAddress = email; } public String getEmailAddress() { return emailAddress; }}
// public Connection getConnection() throws SQLException { /* 实现数据库连接逻辑 */ }
public class Delegate { // 假设 Delegate 包含数据访问逻辑
// 假设 getConnection() 方法已定义并返回一个数据库连接
private Connection getConnection() throws SQLException {
// 实际应用中应从连接池获取或通过其他方式创建连接
throw new UnsupportedOperationException("getConnection() method not implemented.");
}
/**
* 从数据库查询所有符合条件的邮件地址并封装为 UserDto 列表。
* @return 包含所有用户邮件地址的 UserDto 列表。
* @throws RuntimeException 如果发生数据库操作异常。
*/
public List<UserDto> getEmails() { // 方法名改为复数,表示返回多个
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet searchResultSet = null;
try {
connection = getConnection();
preparedStatement = connection.prepareStatement(
"SELECT EMAIL FROM USER WHERE USER.U_SEQ IN ('1','650')");
searchResultSet = preparedStatement.executeQuery();
return extractEmailsFromResultSet(searchResultSet); // 调用辅助方法提取列表
} catch (Exception e) {
throw new RuntimeException("Error fetching emails from database.", e);
} finally {
// 确保 PreparedStatement 和 Connection 资源被关闭
try {
if (searchResultSet != null) searchResultSet.close();
if (preparedStatement != null) preparedStatement.close();
if (connection != null) connection.close();
} catch (SQLException e) {
System.err.println("Error closing database resources: " + e.getMessage());
}
}
}
/**
* 辅助方法:从 ResultSet 中提取所有邮件地址并构建 UserDto 列表。
* @param searchResultSet 数据库查询结果集。
* @return 包含所有用户邮件地址的 UserDto 列表。
* @throws SQLException 如果访问 ResultSet 发生错误。
*/
private List<UserDto> extractEmailsFromResultSet(ResultSet searchResultSet) throws SQLException {
List<UserDto> result = new ArrayList<>();
while (searchResultSet.next()) { // 遍历 ResultSet 中的每一行
UserDto userDto = new UserDto();
userDto.setEmailAddress(searchResultSet.getString(1)); // 获取第一列(EMAIL)的值
result.add(userDto);
}
return result; // 返回完整的 UserDto 列表
}
// 假设 sendNotification 方法已定义
public void sendNotification(String subject, String from, String to, String cc, String bcc, String attachment, String body) {
System.out.println("Sending email to: " + to + " with subject: " + subject);
// 实际的邮件发送逻辑
}
}关键修改点:
在业务逻辑层,现在可以调用修改后的getEmails()方法来获取所有邮件地址的列表,然后使用循环结构逐一处理。
业务逻辑层代码示例:
// 假设 Delegate 和 UserDto 类已在上面定义
public class EmailSenderService {
public static void main(String[] args) {
Delegate delegate = new Delegate(); // 实例化 Delegate
try {
List<UserDto> users = delegate.getEmails(); // 获取所有用户邮件地址列表
if (users != null && !users.isEmpty()) {
String subject = "重要通知";
String body = "这是一封来自系统的通知邮件。";
for (UserDto userDto : users) { // 遍历列表,逐一发送邮件
String toEmail = userDto.getEmailAddress();
if (toEmail != null && !toEmail.trim().isEmpty()) {
delegate.sendNotification(subject, "noreply@example.com", toEmail, "", "", "", body);
System.out.println("Email sent successfully to: " + toEmail);
} else {
System.out.println("Skipping email for user with empty address.");
}
}
} else {
System.out.println("No email addresses found to send notifications.");
}
} catch (RuntimeException e) {
System.err.println("An error occurred during email fetching or sending: " + e.getMessage());
e.printStackTrace();
}
}
}通过上述修改,业务逻辑层能够获取到所有查询到的邮件地址,并通过for循环逐一调用sendNotification方法,从而实现批量邮件发送的功能。
// 使用 try-with-resources 的示例
public List<UserDto> getEmails() {
String sql = "SELECT EMAIL FROM USER WHERE USER.U_SEQ IN ('1','650')";
try (Connection connection = getConnection();
PreparedStatement preparedStatement = connection.prepareStatement(sql);
ResultSet searchResultSet = preparedStatement.executeQuery()) {
return extractEmailsFromResultSet(searchResultSet);
} catch (SQLException e) {
throw new RuntimeException("Error fetching emails from database.", e);
}
}正确地从JDBC ResultSet中提取并处理多条数据是Java数据库应用开发中的基本技能。通过将数据访问层方法设计为返回数据列表,并在业务逻辑层进行迭代处理,可以有效地解决只处理首条记录的问题,实现批量数据操作。同时,遵循良好的资源管理、异常处理和代码规范,将使您的JDBC应用更加健壮和高效。
以上就是Java JDBC:高效批量处理ResultSet中的多条数据的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号