2013-07-21 9 views
10

Recentemente migrato a POSTGRESQL, sto cercando di ottenere la chiave generata in modo univoco sulla creazione di una nuova voce nella tabella db. La tabella screenstable assomiglia a questo:Spring: Come utilizzare KeyHolder con PostgreSQL

CREATE TABLE screenstable 
(
    id serial NOT NULL, 
    screenshot bytea, 
    CONSTRAINT screen_id PRIMARY KEY (id) 
) 

Il metodo che inserisce i dati in screenstable è la seguente:

@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(); 
    } 

e ImageBean è

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; 
    } 
} 

Ma l'esecuzione del codice danno la seguente eccezione

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=[[email protected]}] 
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=[[email protected]}] 
     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)..... 

Lo stesso codice utilizzato per funzionare correttamente in caso di MySQL ma non funziona con le chiavi quando viene utilizzato con POSTGRES. Il tipo di dati serial è in qualche modo responsabile della mancata esecuzione del codice o è possibile che io stia utilizzando correttamente la funzione chiave primaria?

Si prega di consulenza.

risposta

0

Solo una supposizione da un rapido sguardo ... keyHolder.getKey(). IntValue() dovrebbe essere keyHolder.getKey() ["id"]. IntValue() (o qualcosa di simile)? La funzione getKey() restituisce un oggetto con più chiavi (id e immagine) e stai cercando di trasformare l'oggetto in int con la funzione intValue() che immagino non funzioni a meno che tu non punti alla chiave "id" nell'oggetto restituito da "getKey()" Cheers, Francesco

+0

il metodo 'getKey()' restituisce un 'Numero', quindi non riesco ad accedervi come una mappa. si prega di controllare http://static.springsource.org/spring/docs/3.2.x/javadoc-api/org/springframework/jdbc/support/KeyHolder.html –

1

Si può anche stare con JdbcTemplate ma in questa situazione è necessario controllare:

jdbcTemplate.update(this, holder); 
    Long newId; 
    if (holder.getKeys().size() > 1) { 
     newId = (Long)holder.getKeys().get("your_id_column"); 
    } else { 
     newId= holder.getKey().longValue(); 
    } 

il GeneratedKeyHolder classe genera un'eccezione a causa del fatto che la classe solo sa cosa deve essere restituito quando ha una chiave (e quella chiave deve essere Number instance perché il metodo getKey restituisce Number object).

Nella situazione in cui il driver jdbc restituisce più chiavi, è necessario determinare la colonna della chiave generata (prima dell'aggiornamento o dopo). Si prega di dare un'occhiata al codice sorgente di GeneratedKeyHolder # getKey - è molto semplice da analizzare. È in corso il controllo delle dimensioni dell'elenco delle chiavi e con più della chiave Spring non sa quale chiave deve essere restituita ed è per questo che viene restituita l'eccezione.

Nota: Si ricorda che l'approccio non funzionerà con Oracle poiché Oracle restituisce qualcosa come ROWID. Con Oracle è necessario utilizzare NamedParameterJdbcTemplate.

Problemi correlati