使用JdbcTemplate 结合预编译预计批量插入数
- 1. 方法功能概述
- 2. 代码详细分析
- 2.1 预编译语句设置器(BatchPreparedStatementSetter)
- 2.2 数据插入操作
- 3. 整体总结
使用JdbcTemplate 结合预编译预计批量插入数据
1. 方法功能概述
它通过使用预编译语句(PreparedStatement)和 Spring 的 JdbcTemplate 来实现高效的数据插入操作。
2. 代码详细分析
2.1 预编译语句设置器(BatchPreparedStatementSetter)
- 创建与目的:
在方法内部创建了一个匿名内部类实现 BatchPreparedStatementSetter 接口。
这个接口主要用于为批量插入操作中的预编译语句(PreparedStatement)设置参数值。
- getBatchSize() 方法:
功能:该方法用于返回此次要插入数据的批次大小。在这里,它通过获取传入的 batchMessArgs 列表的大小来确定批次大小,告诉数据库服务器本次批量操作涉及的数据量。@Override
public int getBatchSize() {return batchMessArgs.size();
}
- setValues(PreparedStatement ps, int i) 方法:
功能:此方法用于为预编译语句 ps 设置具体的参数值。
对于每一条要插入的数据(由索引 i 确定在批次中的位置),它从 batchMessArgs 列表中获取对应的 LoginLog 对象,
并根据对象的各个属性依次设置预编译语句中的参数。
参数设置细节:
- 对于字符串类型的属性(如 appId、operateType 等),使用 ps.setString() 方法设置参数。
- 对于整数类型的属性(如 result、failCode 等),使用 ps.setInt() 方法设置参数。
- 在设置 create_time 和 update_time 这两个时间戳相关的字段时,先获取当前上海(东八区)的时间(通过
ZonedDateTime.now(ZoneId.of(“Asia/Shanghai”)) 获取 ZonedDateTime 类型的时间),然后将其转换为 Timestamp 类型(通过Timestamp.from(shanghaiTime.toInstant())),最后使用 ps.setTimestamp()方法分别设置这两个字段的值。
代码示例:
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {LoginLog obj = batchMessArgs.get(i);ps.setString(1, obj.getAppId());ps.setString(2, obj.getOperateType());ps.setString(3, obj.getIdentification());ps.setInt(4, de.obj.getResult());ps.setInt(5, obj.getFailCode());ps.setString(6, obj.getOrgId());ps.setInt(7, obj.getAction());ps.setString(8, obj.getPasswordServicePlatformType());ps.setInt(9, obj.getLevel());ps.setString(10, obj.getSource());// 指定时区为上海(东八区)ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));Timestamp timestamp = Timestamp.from(shanghaiTime.toInstant());ps.setTimestamp(11, timestamp);ps.setTimestamp(12, timestamp);
}
2.2 数据插入操作
- SQL 语句定义:
功能:定义了要执行的插入数据的 SQL 语句模板,用于将 LoginLog 类型的数据插入到 login_log 表中。
语句中明确列出了要插入数据的各个字段以及对应的占位符 ?,以便后续通过预编译语句设置具体的值。
final String sql ="insert into login_log (app_id, operate_type, identification, result, fail_code,org_id,action,"+ "password_service_platformType, level, source, create_time, update_time) values"+ " (?,?,?,?,?,?,?,?,?,?,?,?)";
- 执行批量插入:
-
功能:使用 Spring 的 JdbcTemplate 的 batchUpdate() 方法来执行批量插入操作。它传入定义好的
SQL 语句和前面创建的预编译语句设置器 messSetter,这样 JdbcTemplate
就会根据设置器中的逻辑为每一条数据设置参数并执行插入操作。 异常处理:在执行过程中,如果出现异常,会通过日志记录下来(假设 log
是已经正确配置的日志对象),以便后续排查问题。 -
代码示例:
-
// 数据入表try {final String sql ="insert into login_log (app_id, operate_type, identification, result, fail_code,org_id,action,"+ "password_service_platform_type, level, source, create_time, update_time) values"+ " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";jdbcTemplate.batchUpdate(sql, messSetter);} catch (Exception e) {log.error(">>>>>>> messageBatchInsert ", e);}
3. 整体总结
saveAll 方法通过合理利用预编译语句和 Spring 的 JdbcTemplate,高效且准确地实现了将一批 LoginLog 类型的数据批量插入到数据库表中的功能,同时还处理了时间戳相关的设置以及异常情况。这种批量插入的方式可以提高数据插入的效率,减少数据库服务器编译 SQL 语句的次数,从而提升整个应用程序与数据库交互的性能。
private void saveAll(List<LoginLog> batchMessArgs) {// 预编译语句,节省数据库服务器编译 sql 语句的成本BatchPreparedStatementSetter messSetter = new BatchPreparedStatementSetter() {// 用来返回批次的大小@Overridepublic int getBatchSize() {return batchMessArgs.size();}// 用来为PreparedStatement设值。@Overridepublic void setValues(PreparedStatement ps, int i) throws SQLException {LoginLog obj = batchMessArgs.get(i);ps.setString(1, obj.getAppId());ps.setString(2, obj.getOperateType());ps.setString(3, obj.getIdentification());ps.setInt(4, obj.getResult());ps.setInt(5, obj.getFailCode());ps.setString(6, obj.getOrgId());ps.setInt(7, obj.getAction());ps.setString(8, obj.getPasswordServicePlatformType());ps.setInt(9, obj.getLevel());ps.setString(10, obj.getSource());// 指定时区为上海(东八区)ZonedDateTime shanghaiTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));Timestamp timestamp = Timestamp.from(shanghaiTime.toInstant());ps.setTimestamp(11, timestamp);ps.setTimestamp(12, timestamp);}};// 数据入表try {final String sql ="insert into login_log (app_id, operate_type, identification, result, fail_code,org_id,action,"+ "password_service_platform_type, level, source, create_time, update_time) values"+ " (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";jdbcTemplate.batchUpdate(sql, messSetter);} catch (Exception e) {log.error(">>>>>>> messageBatchInsert ", e);}}