如何批量操纵SQL

70 阅读3分钟

批量操作SQL语句具有以下好处:

  1. 提高性能:相较于逐条执行SQL语句,批量操作可以减少与数据库之间的通信次数,从而提高整体性能。通过减少网络开销和数据库连接的建立和关闭,可以大大减少查询和更新的时间。
  2. 减少资源消耗:批量操作可以减少数据库服务器的负载,减少CPU和内存的使用,从而节省服务器资源。这对于高并发环境或大量数据处理场景特别重要,可以更好地利用服务器资源。
  3. 原子性和一致性:批量操作可以将多个SQL语句作为一个事务进行处理,从而保证了原子性和一致性。如果在一批操作中的某个步骤出现错误,整个批量操作可以回滚,保证数据库的完整性。
  4. 简化代码:批量操作可以简化代码逻辑。通过批量操作,你可以将多个操作组合到一起,减少重复的代码和冗余的数据库操作。这样可以提高代码的可读性和维护性。
  5. 提升用户体验:对于需要处理大量数据的任务,批量操作可以显著减少处理时间,提升用户体验。用户不需要等待每个操作完成,而是在一次请求后即可得到结果。

具体实现步骤

1、创建mapper文件编写sql语句

/**
 * 修改仓库的库存
 * @param orderDetail
 */
@Update("UPDATE item SET stock = stock - #{num} WHERE id = #{itemId}")
void updateStock(OrderDetailDTO orderDetail);

注意:使用mybatisplus此步可以省略

2、编写批量操作sql语句函数

@Override
public void deductStock(List<OrderDetailDTO> items) {
    String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock";
    boolean r = false;
    try {
        r = executeBatch(items, (sqlSession, entity) -> {
            sqlSession.update(sqlStatement, entity);
        });
    } catch (Exception e) {
        log.error("更新库存异常", e);
        return;
    }
    if (!r) {
        throw new BizIllegalException("库存不足!");
    }
}

代码解释:

  1. 首先,该方法接受一个参数 List<OrderDetailDTO> items,表示需要扣减库存的商品列表。
  2. String sqlStatement = "com.hmall.item.mapper.ItemMapper.updateStock"; 定义了一个字符串变量 sqlStatement,用于表示需要执行的 SQL 语句。
  3. executeBatch 方法是一个自定义的批量操作方法,接受一个 List 和一个回调函数作为参数。这个方法在 try-catch 块中被调用,并将结果赋给 r 变量。
  4. executeBatch 方法会遍历传入的商品列表,并对每个商品进行库存扣减操作。具体的扣减逻辑在回调函数中实现。
  5. 在回调函数中,sqlSession.update(sqlStatement, entity); 执行了一次数据库更新操作,使用了 MyBatis 的 update 方法。该方法根据 sqlStatement 执行指定的 SQL 语句,并将 entity 作为参数传递给 SQL 语句。
  6. 如果批量操作执行成功,r 的值为 true,否则为 false
  7. 如果批量操作执行失败(捕获到异常),则记录日志并返回,不抛出异常。
  8. 最后,如果 r 的值为 false,表示库存不足,抛出 BizIllegalException 异常,提示用户库存不足。

3、代码调用

// 批量操作
List<OrderDetailDTO> execute = new ArrayList<>();
OrderDetailDTO detailDTO01 = new OrderDetailDTO();
OrderDetailDTO detailDTO02 = new OrderDetailDTO();
detailDTO01.setItemId(317578L); // 317578
detailDTO01.setNum(1000);
detailDTO02.setItemId(317580L); // 317578
detailDTO02.setNum(1000);

execute.add(detailDTO01);
execute.add(detailDTO02);
itemClient.executeBatchTest(execute);

作者:vitos