2015-05-07 3 views
1

У меня есть таблица с авто увеличивается первичный ключ, а также уникальный ключ:Mysql на дубликат ключа обновления с первичным ключом и уникальным ключом

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`) 

Im используя на дубликата ключа функции для обновления записей, если 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 следует использовать только тогда, когда один ключ возвращается. Текущая ключевая запись содержит несколько ключей: [{GENERATED_KEY = 594}, {GENERATED_KEY = 595}]

Кто-нибудь знает, что вызывает это?

ответ

3

Я просто столкнулся с этим сам. Согласно документации здесь:

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

With ON DUPLICATE KEY UPDATE, the affected-rows value per row is 1 if the row is inserted as a new row, and 2 if an existing row is updated.

Таким образом, когда ваш запрос выполняется, если новая запись вставляется его ID возвращается. Если запись уже существует, обновляется существующая запись. Если обновление не требуется, потому что все значения совпадают, тогда возвращается идентификатор, а число измененных строк равно 0. Однако, если запись обновлена, идентификатор возвращается и число измененных строк равно . Бланкхолдер предполагает, что две строки были изменены (хотя только один из них был) и неправильно возвращают идентификатор плюс следующий последовательный идентификатор (т. Е. ID плюс 1).

Чтобы обойти это, я просто проверил счет в getKeys, прежде чем пытаться вызвать getKey. Если в getKeys имеется более одного значения, я не буду называть getKey.

+0

Спасибо! Я закончил делать что-то подобное, но напрямую использовал JDBC. В моем случае я хотел получить идентификатор даже во время обновления. С JDBC я все еще могу получить идентификатор, даже если возвращаются две строки, но шаблон весны взрывается :( –

Смежные вопросы