Java JDBCTemplate检索上次\u INSERT\u ID()mySQL技巧设置的值时出现问题
我在使用mySQL和SpringJDBCTemplate时遇到了一些问题。我有一个插页。。。在重复密钥更新中,它增加一个计数器,但使用LAST_INSERT_ID技巧通过最后生成的ID在同一查询中返回新值。我正在使用PreparedStatementCreator和GeneratedKeyHolder的JDCTemplate.UPDATE,但在KeyHolder.getKeyList中获得多个条目。当我在mySQL客户机中手动运行它时,当它点击重复密钥更新,然后选择LAST_INSERT_ID时,我会得到2行影响;给我正确的值 更新:看起来键列表中的3个条目都有1个条目,它们都是递增值。因此keyList.get0.get0具有应该返回的值,然后keyList.get0.get1是前一个值+1,然后keyList.get0.get2是前一个值+1。例如,如果4是应该返回的值,它按顺序给出4,5,6 有关守则如下:Java JDBCTemplate检索上次\u INSERT\u ID()mySQL技巧设置的值时出现问题,java,mysql,spring,jdbctemplate,Java,Mysql,Spring,Jdbctemplate,我在使用mySQL和SpringJDBCTemplate时遇到了一些问题。我有一个插页。。。在重复密钥更新中,它增加一个计数器,但使用LAST_INSERT_ID技巧通过最后生成的ID在同一查询中返回新值。我正在使用PreparedStatementCreator和GeneratedKeyHolder的JDCTemplate.UPDATE,但在KeyHolder.getKeyList中获得多个条目。当我在mySQL客户机中手动运行它时,当它点击重复密钥更新,然后选择LAST_INSERT_ID时
CREATE TABLE IF NOT EXISTS `ClickChargeCheck` (
uuid VARCHAR(50),
count INTEGER Default '0',
CreatedOn Timestamp DEFAULT '0000-00-00 00:00:00',
UpdatedOn Timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
String CLICK_CHARGE_CHECK_QUERY = "INSERT INTO ClickChargeCheck (uuid,count,CreatedOn) VALUES(?,LAST_INSERT_ID(1),NOW()) ON DUPLICATE KEY UPDATE count = LAST_INSERT_ID(count+1)";
...
...
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
centralStatsJdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(CLICK_CHARGE_CHECK_QUERY, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, uuid);
return ps;
}}, keyHolder);
int count = keyHolder.getKey().intValue();
结果表明,mySQL的PreparedStatement运行该查询,并说它返回3行。因此,getGeneratedKeys调用委托给StatementImpl.getGeneratedKeysInternal,因为它看到返回的3行,所以它获取第一个最后一个插入ID值,然后从那里递增到行数。因此,我必须获取GeneratedKeyHolder.getKeyList并获取第一个条目,然后获取它的第一个值,这就是我需要的值。对于我来说,我遇到了同样的问题。对于INSERT…在重复密钥更新时,GeneratedKeyHolder抛出了一个异常,因为它期望只有一个返回的密钥,而MySQL则不是这样。我基本上必须实现一个新的KeyHolder实现,它可以处理多个返回的密钥
public class DuplicateKeyHolder implements KeyHolder {
private final List<Map<String, Object>> keyList;
/* Constructors */
public Number getKey() throws InvalidDataAccessApiUsageException, DataRetrievalFailureException {
if (this.keyList.isEmpty()) {
return null;
}
Iterator<Object> keyIter = this.keyList.get(0).values().iterator();
if (keyIter.hasNext()) {
Object key = keyIter.next();
if (!(key instanceof Number)) {
throw new DataRetrievalFailureException(
"The generated key is not of a supported numeric type. " +
"Unable to cast [" + (key != null ? key.getClass().getName() : null) +
"] to [" + Number.class.getName() + "]");
}
return (Number) key;
} else {
throw new DataRetrievalFailureException("Unable to retrieve the generated key. " +
"Check that the table has an identity column enabled.");
}
}
public Map<String, Object> getKeys() throws InvalidDataAccessApiUsageException {
if (this.keyList.isEmpty()) {
return null;
}
return this.keyList.get(0);
}
public List<Map<String, Object>> getKeyList() {
return this.keyList;
}
}
如果您只是在使用GeneratedKeyHolder的地方使用这个类,那么一切都可以正常工作。我发现你甚至不需要添加。。。在重复密钥更新id=上次插入id时。。。在insert语句中