如何使用带有 Spring JDBC 的 MERGE 语句插入/更新单个记录

Posted

技术标签:

【中文标题】如何使用带有 Spring JDBC 的 MERGE 语句插入/更新单个记录【英文标题】:How to insert/update a single record using a MERGE statement with Spring JDBC 【发布时间】:2018-08-06 16:03:43 【问题描述】:

我有一个使用 MERGE 语句创建的更新/插入 SQL 查询。使用 JdbcTemplate 或 NamedParameterJdbcTemplate,Spring 是否提供了一种我可以用来更新单个记录的方法,而不是批量更新?

由于此查询将用于通过 JMS 侦听器从队列中持久化数据,因此我一次只将一条记录出列,并且不需要批量更新的开销。

如果批处理是通过 Spring JDBC 执行此操作的唯一方法,那很好......我只是想确保我没有遗漏一些更简单的东西。

【问题讨论】:

只需使用update 方法,例如这个:JdbcTemplate#update 而不是BatchUpdate。 Update更新单条记录,batchUpdate使用JDBC批量更新多条记录。 @krokodiko:谢谢!这正是我需要知道的。你是第一个,所以如果你提供一个正式的答案,我会投票给你的答案。每个人都乐于助人。我最初尝试了 Spring 的更新方法,但由于我的参数化列表有问题,我误解了异常并确定 UPDATE 不是正确的方法。我没有意识到使用 Spring JDBC,它只是一个单一的或批量的更新。我寻找了一种更具体的方法,但找不到,所以你的简短回答给了我解决问题所需的洞察力。谢谢你的回答! 【参考方案1】:

您可以使用 SQL MERGE 语句,只使用包含您的参数的单行查询。

例如,如果您有一个表 COMPANYcontaing ID 作为键,NAME 作为属性,MERGE 语句将是:

merge into company c
using (select ? id, ? name from dual) d
on (c.id = d.id)
when matched then update 
   set c.name = d.name
when not matched then insert (c.id, c.name)
   values(d.id, d.name)

如果您的目标表包含参数化键,name 将被更新,否则将插入一条新记录。

使用 JDBCTemplate,您可以使用 update 方法调用 MERGE 语句,如下图所示(使用 Groovy 脚本)

def id = 1
def name = 'NewName'

String mergeStmt = """merge into company c
using (select ? id, ? name from dual) d
on (c.id = d.id)
when matched then update 
   set c.name = d.name
when not matched then insert (c.id, c.name)
   values(d.id, d.name)""";

def updCnt = jdbcTemplate.update(mergeStmt, id, name);

println "merging $id, name $name, merged rows $updCnt" 

【讨论】:

我用过Java,但你的回答绝对正确。感谢您分享这个例子。尽管我已经使用 Spring JDBC 中的 update 方法多年,但我对 MERGE 语句还是新手,并没有意识到 update 方法足够通用,可以处理更新和插入的 SQL 语句。我实际上已经简单地尝试过,但是我的参数化列表有问题。在那之后,我一直在寻找一种更具体的方法,也许是为执行 MERGE 而构建的。谢谢你的例子!【参考方案2】:

只需使用update 方法之一,例如:JdbcTemplate#update 而不是 BatchUpdate。 Update更新单条记录,batchUpdate使用JDBC批量更新多条记录

【讨论】:

以上是关于如何使用带有 Spring JDBC 的 MERGE 语句插入/更新单个记录的主要内容,如果未能解决你的问题,请参考以下文章

带有 jdbc 的 Spring Security 3.0

Spring JDBC:如何创建表?

带有 JDBC 配置的 Spring-Session:表 'test.spring_session' 不存在

带有 JDBC 身份验证的 Spring Security 5:UserDetailsS​​ervice bean 仍然在内存中,而不是 JDBC

带有 MyBatis 的 Spring Data JDBC 找不到自定义查询

带有布尔全文搜索格式问题的spring jdbc准备语句