Java JDBCTemplate检索上次\u INSERT\u ID()mySQL技巧设置的值时出现问题

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时

我在使用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

有关守则如下:

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语句中