问题
Recently migrated to POSTGRESQL, I am trying to obtain the uniquely generated key on creating a new entry into the db table. The table screenstable
looks like this:
CREATE TABLE screenstable
(
id serial NOT NULL,
screenshot bytea,
CONSTRAINT screen_id PRIMARY KEY (id )
)
The method that inserts data into screenstable
is as follows:
@Autowired NamedParameterJDBCTemplate template;
public int insertImage(ImageBean imageBean){
String query = "insert into screenstable (screenshot) values (:image)";
SqlParameterSource data = new BeanPropertySqlParameterSource(imageBean);
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(query, data, keyHolder);
return keyHolder.getKey().intValue();
}
and ImageBean
is
import java.util.Arrays;
public class ImageBean {
private int id;
private byte[] image;
@Override
public String toString() {
return "ImageBean [id=" + id + ", image=" + Arrays.toString(image)
+ "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public byte[] getImage() {
return image;
}
public void setImage(byte[] image) {
this.image = image;
}
}
But running the code give the following exception
15:33:20,953 ERROR JsonParseExceptionMapper:15 - org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned. The current key entry contains multiple keys: [{id=3, screenshot=[B@db59df}]
org.springframework.dao.InvalidDataAccessApiUsageException: The getKey method should only be used when a single key is returned. The current key entry contains multiple keys: [{id=3, screenshot=[B@db59df}]
at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:65)
at some.project.model.FeedbackDao.insertImage(FeedbackDao.java:20)
at some.project.rest.FeedsRest.pluginCheck(FeedsRest.java:62)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597).....
The same code used to run fine in case of MySQL
but is failing with keys when used with POSTGRES. Is the datatype serial
somehow responsible for the code failing or may be I am using the primary key feature correctly?
Please advice.
回答1:
If the framework is not informed about which column is the key, it will return all columns of the table as keys.
You can inform it by passing a new parameter to the update method, as follows:
template.update(query, data, keyHolder, new String[] { "id" });
See NamedParameterJdbcTemplate.update(sql, paramSource, generatedKeyHolder, keyColumnNames)
回答2:
You can also stay with JdbcTemplate but in this situation you have to check it:
jdbcTemplate.update(this, holder);
Long newId;
if (holder.getKeys().size() > 1) {
newId = (Long)holder.getKeys().get("your_id_column");
} else {
newId= holder.getKey().longValue();
}
The GeneratedKeyHolder class throws exception due to the fact that class only knows what should be returned when has one key (and that key needs to be Number instance because getKey method returns Number object).
On situation when jdbc driver return multiple keys you have to determine the generated key column (either before update or after). Please take a look at source code of the GeneratedKeyHolder#getKey - it is very simple to analyze. There is checking of key list size and with more than key Spring does not know which key should be returned and that's why the exception is returned.
Note: Please remember that approach won't work with Oracle because Oracle returns something like ROWID. With Oracle you have to use NamedParameterJdbcTemplate.
回答3:
Just a guess from a quick look... keyHolder.getKey().intValue() should be keyHolder.getKey()["id"].intValue() (or something similar)? getKey() function returns an object with multiple keys (id and image) and you are trying to turn the object to int with intValue() function which I guess does not work unless you point to the "id" key in the object returned from "getKey()" Cheers, Francesco
来源:https://stackoverflow.com/questions/17771306/spring-how-to-use-keyholder-with-postgresql