*/
private KeyHolder executeInsertAndReturnKeyHolderInternal(final List<Object> values) {
if (logger.isDebugEnabled()) {
logger.debug("The following parameters are used for call " + getInsertString() + " with: " + values);
}
final KeyHolder keyHolder = new GeneratedKeyHolder();
if (this.tableMetaDataContext.isGetGeneratedKeysSupported()) {
getJdbcTemplate().update(
new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = prepareStatementForGeneratedKeys(con);
setParameterValues(ps, values, getInsertTypes());
return ps;
}
},
keyHolder);
}
else {
if (!this.tableMetaDataContext.isGetGeneratedKeysSimulated()) {
throw new InvalidDataAccessResourceUsageException(
"The getGeneratedKeys feature is not supported by this database");
}
if (getGeneratedKeyNames().length < 1) {
throw new InvalidDataAccessApiUsageException("Generated Key Name(s) not specified. " +
"Using the generated keys features requires specifying the name(s) of the generated column(s)");
}
if (getGeneratedKeyNames().length > 1) {
throw new InvalidDataAccessApiUsageException(
"Current database only supports retrieving the key for a single column. There are " +
getGeneratedKeyNames().length + " columns specified: " + Arrays.asList(getGeneratedKeyNames()));
}
// This is a hack to be able to get the generated key from a database that doesn't support
// get generated keys feature. HSQL is one, PostgreSQL is another. Postgres uses a RETURNING
// clause while HSQL uses a second query that has to be executed with the same connection.
final String keyQuery = this.tableMetaDataContext.getSimulationQueryForGetGeneratedKey(
this.tableMetaDataContext.getTableName(), getGeneratedKeyNames()[0]);
Assert.notNull(keyQuery, "Query for simulating get generated keys can't be null");
if (keyQuery.toUpperCase().startsWith("RETURNING")) {
Long key = getJdbcTemplate().queryForObject(getInsertString() + " " + keyQuery,
values.toArray(new Object[values.size()]), Long.class);
Map<String, Object> keys = new HashMap<String, Object>(1);
keys.put(getGeneratedKeyNames()[0], key);
keyHolder.getKeyList().add(keys);
}
else {
getJdbcTemplate().execute(new ConnectionCallback<Object>() {
@Override
public Object doInConnection(Connection con) throws SQLException, DataAccessException {
// Do the insert
PreparedStatement ps = null;
try {
ps = con.prepareStatement(getInsertString());
setParameterValues(ps, values, getInsertTypes());
ps.executeUpdate();
}
finally {
JdbcUtils.closeStatement(ps);
}
//Get the key
Statement keyStmt = null;
ResultSet rs = null;
Map<String, Object> keys = new HashMap<String, Object>(1);
try {
keyStmt = con.createStatement();
rs = keyStmt.executeQuery(keyQuery);
if (rs.next()) {
long key = rs.getLong(1);
keys.put(getGeneratedKeyNames()[0], key);
keyHolder.getKeyList().add(keys);
}
}
finally {
JdbcUtils.closeResultSet(rs);
JdbcUtils.closeStatement(keyStmt);