使用主键和唯一键

时间:2015-05-07 16:58:34

标签: 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`)

如果canonical_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 个答案:

答案 0 :(得分:7)

我自己就碰到了这个。根据这里的文件:

https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html

  

如果ON DUPLICATE KEY UPDATE,如果将行作为新行插入,则每行的受影响行值为1;如果更新现有行,则 2

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

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