我有一个表,其中包含一个自动递增的主键和一个唯一键:
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已经存在,我正在使用复制密钥功能更新记录:
"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方法。当前密钥条目包含多个密钥:[{GENERED_KEY=594},{GENERATED_KEY=595}]
有人知道这是什么原因吗?
2条答案
按热度按时间cmssoen21#
这是我自己刚遇到的。根据此处的文档:
https://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
使用ON DIPLICATE KEY UPDATE时,如果该行作为新行插入,则每行受影响的行值为1,如果更新现有行,则为2。
因此,当执行查询时,如果插入新记录,则返回其ID。如果该记录已经存在,则更新现有记录。如果因为值都匹配而不需要更新,则返回一个ID,修改的行数为0。但是,如果更新记录,则返回ID,修改的行数为2。密钥持有者假设已经修改了两行(即使只修改了一行),并且错误地返回了ID加上下一个顺序ID(即ID加1)。
为了解决这个问题,在尝试调用getkey之前,我只检查了getKey中的计数。如果getKeys中有多个值,我就不会调用GetKey。
6kkfgxo02#
假设在重复的情况下,临时插入的行将具有更大的id,以下是一种解决方法:
但请注意,
keyHolder.getKey()
是java.math.BigInteger
的示例,所以我不确定这将如何与具有非常大值的id
一起工作。