一种将多个记录一起插入的方法?

Posted

技术标签:

【中文标题】一种将多个记录一起插入的方法?【英文标题】:A way to upsert multiple records together? 【发布时间】:2022-01-16 16:10:38 【问题描述】:

我正在尝试看看是否有办法改进数据的插入和更新方式。

我正在使用带有 JDBC 的 ORACLE DB。

我目前的做法是在检查 toUpdate 是否为 true 之后使用 FOR 循环更新(例如)客户记录。一个示例,例如下面的示例代码,然后调用现有的 DAO update() 来执行此操作。但这不允许将多个数据合并在一起。

但是,有没有更好的方法将多个数据一起 UPSERT?

        if (toUpdate) 
            for (Customer customerRec : customerRecList) 
                customerRecDAO.update(customerRec);
        

【问题讨论】:

你使用的是spring JDBC模板吗? 在 Spring-boot 中使用 spring data jpa 我们有 saveAll()。如果spring JDBC通过tutorialspoint.com/spring/spring_jdbc_example.htm 【参考方案1】:

是的,您可以使用批处理:

public <T> int saveInBatch(List<T> records, String sql, Function<T, MapSqlParameterSource> paramFn)

try
MapSqlParameterSource[] params = records.stream().map(paramFn).toArray(MapSqlParameterSource[]::new);
int rowCount = jdbcTemplate.batchUpdate(sql, params);
return Arrays.stream(rowCount).sum();

catch(Exception e)
//exception handling 



paramFn 是一个 lambda 函数,您可以将记录映射到它们的值。示例可能是

(record)->
return new MapSqlParameterSource("username" ,username),Integer.class);//just example

why we use MapSqlParameterSource

您可以通过传递较小批次或自定义批次记录的方式调用 saveInBatch。假设您有一百万条记录,那么您可能希望一次只更新 200-400 条记录,因此您可以执行以下操作:

private <T> int saveRecords(List<T> records, String sql, Function<T, MapSqlParameterSource> paramFn) throws Exception

return Lists.partition(records, 300).stream().map(batch-> saveInBatch(batch, sql, paramFn)).mapToInt(Integer::intValue).sum();

上面的Note: 没有得到很好的优化,或者没有充分利用流,但这是我很久以前尝试过的有效代码:)。

【讨论】:

以上是关于一种将多个记录一起插入的方法?的主要内容,如果未能解决你的问题,请参考以下文章

寻找一种将 select2 控件与 tablesorter 的内部过滤器小部件一起使用的方法

laravel 在插入之前检查记录是不是存在,这是一种有效的方法

在不使用 jquery/ajax 的情况下自动将新记录插入到表中时,使用新记录更新页面的另一种方法是啥

在 GreenPlum 中插入

在使用多个数据库时将记录插入表的 ManyToMany 字段

设计一种审计表更改的方法