Ottenere quasi il doppio della lunghezza durante la lettura di byte da postgres con jpa

Ho una class Image che ha un byte [] per contenere i dati reali dell’immagine. Sono in grado di caricare e inserire l’immagine bene nella mia webapp. Quando provo a visualizzare l’immagine dopo averla letta da JPA, la lunghezza del mio byte [] è sempre o 2x-1 o 2x-2, dove x è la lunghezza del campo bytea in postgres 9. Ovviamente il browser non verrà visualizzato l’immagine dice che è corrotta. Potrei usare un po ‘di aiuto per capire perché sto ricevendo (circa) il doppio di quello che mi aspetto. Ecco la mapping della mia class di immagini. Usando eclipselink con JPA 2 che colpisce postgres 9 su un mac.

Quando seleziono dal database con

select *, length(bytes) from image; 

Ottengo una lunghezza di 9765. In un punto di interruzione nel mio controller la lunghezza del byte [] è 19529, che è un byte meno del doppio di ciò che è nel database.

 @Entity @Table( name = "image" ) @SequenceGenerator( name = "IMAGE_SEQ_GEN", sequenceName = "IMAGE_SEQUENCE" ) public class Image extends DataObjectAbstract { @Id @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "IMAGE_SEQ_GEN" ) private Long key; @Column( name="content_type" ) private String contentType; @Lob @Basic( optional=false ) @Column( name="bytes" ) private byte[] bytes; // constructor and getters and setters } 

pgadmin mi mostra quanto segue per la tabella immagini

 CREATE TABLE image ( "key" bigint NOT NULL, bytes bytea, content_type character varying(255), "version" integer, CONSTRAINT image_pkey PRIMARY KEY (key) ) WITH ( OIDS=FALSE ); 

In PostgreSQL 9 byte [] viene inviato al client usando la codifica esadecimale.

Se questo è motivo di errore, devi trovare l’aggiornamento per JPA. O si può cambiare la configurazione del server DB, ma precedente è meglio.

“Bytea_output = escape” è solo una soluzione, Postgres 8.0 ha cambiato la codifica bytea in hex.

Utilizzare un driver JDBC corrente dal 9.0-dev800 (9.0 Build 801 è aggiornato al momento) e il problema verrà risolto.

Risposta aggiuntiva per gli utenti GlassFish 3.x (i principi possono essere applicati ad altri server delle app)

È ansible che si stia inavvertitamente utilizzando un vecchio driver JDBC PostgreSQL. È ansible verificare ciò iniettando un DataSource da qualche parte (ad esempio un EJB) ed eseguendo quanto segue su di esso:

System.out.println(ds.getConnection().getMetaData().getDriverVersion());

Nel mio caso, era 8,3 che era inaspettato da quando stavo distribuendo con 9.1 driver.

Per scoprire da dove proveniva:

System.out.println(Class.forName("org.postgresql.Driver").getProtectionDomain().getCodeSource().getLocation());

Come risultato per me, era nella directory lib del mio dominio GlassFish. Non sono sicuro di come sia arrivato – GlassFish di certo non viene spedito in questo modo – così l’ho rimosso e il problema è andato via.

Prova a guardare i dati che stai ricevendo. Potrebbe darti un’idea di cosa sta succedendo.

Controlla se hai un vecchio barattolo postgresql. Ho affrontato lo stesso problema, e ho trovato sia il jar postgresql 8.3 che un jar postgresql 9.1 nella mia libreria. Dopo aver rimosso 8.3 postgresql, byte [] funziona correttamente.