I’m having some trouble using mySQL and Spring JDBCTemplate. I have an INSERT … ON DUPLICATE KEY UPDATE which increments a counter, but uses the LAST_INSERT_ID() trick to return the new value in the same query through the last generated id. I’m using JDCTemplate.update() with the PreparedStatementCreator and GeneratedKeyHolder, but I’m getting multiple entries in the KeyHolder.getKeyList(). When I run it manually in the mySQL client, I’m getting 2 rows affected (when it hits the DUPLICATE KEY UPDATE), and then the SELECT LAST_INSERT_ID(); gives me the correct value.
UPDATE: It looks like the 3 entries in the keyList all have 1 entry each, and they are all incrementing values. So keyList.get(0).get(0) has the value that should be returned, and then keyList.get(0).get(1) is the previous value +1, and then keyList.get(0).get(2) is the previous value +1. So for example, if 4 is the value that should be returned, it gives me 4, 5, 6 in that order.
The relevant code is:
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();
Turns out that mySQL’s PreparedStatement runs that query, and says it returns 3 rows. So the getGeneratedKeys() call (delegated to StatementImpl.getGeneratedKeysInternal()) which, since it sees 3 rows returned, grabs the first LAST_INSERT_ID() value, and then increments from there up to the number of rows. So, I’ll have to grab the GeneratedKeyHolder.getKeyList() and grab the first entry, and get it’s first value and that’ll be the value I need.