Mysql使用主键和唯一键进行重复密钥更新

Mysql使用主键和唯一键进行重复密钥更新,mysql,spring-jdbc,Mysql,Spring Jdbc,我有一个带有自动递增主键和唯一键的表: CREATE TABLE `product` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `canonical_url` varchar(750) CHARACTER SET latin1 NOT NULL, ... PRIMARY KEY (`id`), UNIQUE KEY `canonical_url_idx` (`canonical_url`) 如果规范的url已经存在,我将使用on duplicate

我有一个带有自动递增主键和唯一键的表:

CREATE TABLE `product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`canonical_url` varchar(750) CHARACTER SET latin1 NOT NULL,
...
PRIMARY KEY (`id`),
UNIQUE KEY `canonical_url_idx` (`canonical_url`)
如果规范的url已经存在,我将使用on duplicate key功能更新记录:

"INSERT INTO product(id, canonical_url, name VALUES(?, ? ?) ON DUPLICATE KEY UPDATE name=VALUES(name), id=LAST_INSERT_ID(id)"

KeyHolder productKeyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(conn -> {
  PreparedStatement ps = conn.prepareStatement(productSql, new String[] {"id"});
  ps.setInt(1, id);
  ps.setString(2, canonicalUrl);
  ps.setString(3, name);
}, productKeyHolder);

final int productId = productKeyHolder.getKey().intValue();
问题是我遇到了以下错误:

getKey方法只能在返回单个键时使用。当前密钥项包含多个密钥:[{GENERATED_key=594},{GENERATED_key=595}]


有人知道这是什么原因吗?

我自己也遇到过。根据此处的文档:

使用“在重复键更新时”,如果将行作为新行插入,则每行受影响的行值为1;如果更新现有行,则每行受影响的行值为2

因此,当您的查询执行时,如果插入了一条新记录,则会返回其ID。如果记录已存在,则更新现有记录。如果由于所有值都匹配而不需要更新,则返回一个ID,修改的行数为0。但是,如果更新记录,则返回ID,修改的行数为2。密钥持有者假设两行已被修改(即使只有一行已被修改),并且错误地返回ID加上下一个顺序ID(即ID加1)


为了解决这个问题,在尝试调用getKey之前,我只检查了getKey中的计数。如果getKey中有多个值,我不会调用getKey。

谢谢!我最终做了类似的事情,但直接使用JDBC。在我的例子中,我甚至想在更新期间获得ID。使用JDBC,即使返回了两行,我仍然可以获得ID,但是spring的模板崩溃了:(仅供参考,我刚刚使用
spring-boot-2.0.5.RELEASE遇到了相同的问题