Michel Zanini opened SPR-9236 and commented
If you have table or column names that are reserved SQL words, like "varchar", "values", "integer", etc... the generated insert SQL must have escaping.
For example, now SimpleJdbcInsert
is generating this SQL:
INSERT INTO crud (text, integer, char, datetime, decimal, varchar) VALUES(?, ?, ?, ?, ?, ?)
but it should be generating this:
INSERT INTO `crud` (`text`, `integer`, `char`, `datetime`, `decimal`, `varchar`) VALUES(?, ?, ?, ?, ?, ?)
As a workaround I am able to make it work adding the escape char "`" to the column names like this:
simpleJdbcInsert.withTableName("`" + tableName + "`");
simpleJdbcInsert.usingColumns("`" + column1 + "`", "`" + column2 + "`", "`" + column3 + "`");
but I believe SimpleJdbcInsert
should support this out of the box. For example, it could have a boolean property like this:
simpleJdbcInsert.withTableName(tableName);
simpleJdbcInsert.usingColumns(column1, column2, column3);
simpleJdbcInsert.usingEscaping(true);
and then SimpleJdbcInsert
would do the escaping for me.
Affects: 3.1.1
4 votes, 6 watchers
Comment From: spring-projects-issues
Michel Zanini commented
Actually, escaping the columns like shown here does NOT work. It is inserting null values for all columns.
Comment From: spring-projects-issues
Chris Beams commented
Added @thomas
.risberg as watcher. Thomas, could you comment here?
Comment From: spring-projects-issues
Thomas Risberg commented
That escaping would only work for MySQL. Would be better to add support for quoted identifiers and in that case we would have to make sure we match the case used for the column names.
We could add usingQuotedIdentifiers(true)
and generate something like this:
INSERT INTO "CRUD" ("text", "integer", "char", "datetime", "decimal", "varchar") VALUES(?, ?, ?, ?, ?, ?)
We would need to get the quote character to use from the database metadata --http://docs.oracle.com/javase/6/docs/api/java/sql/DatabaseMetaData.html#getIdentifierQuoteString%28%29
Seems like a worthwhile improvement though.
-Thomas
Comment From: spring-projects-issues
Michel Zanini commented
I agree. Looking forward to have this.
Comment From: spring-projects-issues
Lephix Long commented
Why this issue last so long?
Comment From: spring-projects-issues
reda abdi commented
any workaround?
Comment From: spring-projects-issues
TotoTata commented
Really ? Since 2012 and no corrections ? There are 1000+ MySQL keywords so making column name without it is nearly impossible, so using SimpleJdbcInsert is also impossible. It's not that hard to had ' in created SQL query. I can't understand how a bug like this can still be here.
I'm using this for workaround:
String INSERT_SQL = "insert into CUSTOMER (NAME) values (?)";
KeyHolder key = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
final PreparedStatement ps = connection.prepareStatement(INSERT_SQL,
Statement.RETURN_GENERATED_KEYS);
ps.setString(1, name);
return ps;
}
}, key);
return key.getKey().longValue();
Comment From: vhrankina
We need the same functionality for PostgreSQL because we use a mix of uppercase and lowercase letters for table names and we need to escape them with double quotes. When I set table name with double quotes like so
new SimpleJdbcInsert(dataSource)
.withTableName("\"Table_Name\"");
I see a log message that metadata for table not found.
Comment From: sadafzohra19
It worked for me. What I did is,
String[] columns = {"name", "desc", "code", "`order`"}
SimpleJdbcInsert insert = new SimpleJdbcInsert(getJdbcTemplate());
insert.withTableName(tableName);
insert.usingColumns(columns);
insert.usingGeneratedKeyColumns("id");
Number id = insert.executeAndReturnKey(parameterSource);
Note that in order to pass parameter for column "order", you need to pass it like:
params.put("`order`", 3);
Comment From: sbrannen
- superseded by #24013