PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Impossibile memorizzare il simbolo dell'euro nella proprietà String LOB con Hibernate/PostgreSQL

Dopo molte ricerche nel codice sorgente di Hibernate e nel driver JDBC di PostgreSQL, sono riuscito a trovare la causa principale del problema. Alla fine viene invocato il metodo write() del BlobOutputStream (fornito dal driver JDBC) per scrivere il contenuto del Clob nel database. Questo metodo è simile al seguente:

public void write(int b) throws java.io.IOException
{
    checkClosed();
    try
    {
        if (bpos >= bsize)
        {
            lo.write(buf);
            bpos = 0;
        }
        buf[bpos++] = (byte)b;
    }
    catch (SQLException se)
    {
        throw new IOException(se.toString());
    }
}

Questo metodo prende un 'int' (32 bit/4 byte) come argomento e lo converte in un 'byte' (8 bit/1 byte) perdendo di fatto 3 byte di informazioni. Le rappresentazioni di stringhe all'interno di Java sono codificate in UTF-16, il che significa che ogni carattere è rappresentato da 16 bit/2 byte. Il segno dell'euro ha il valore int 8364. Dopo la conversione in byte, il valore rimane 172 (nella rappresentazione dell'ottetto 254).

Non sono sicuro di quale sia ora la migliore soluzione a questo problema. IMHO il driver JDBC dovrebbe essere responsabile della codifica/decodifica dei caratteri Java UTF-16 in qualsiasi codifica necessaria al database. Tuttavia, non vedo alcuna possibilità di ritocco nel codice del driver JDBC per alterarne il comportamento (e non voglio scrivere e mantenere il mio codice del driver JDBC).

Pertanto, ho esteso Hibernate con un ClobType personalizzato e sono riuscito a convertire i caratteri UTF-16 in UTF-8 prima di scrivere nel database e viceversa durante il recupero del Clob.

Le soluzioni sono troppo grandi per incollare semplicemente in questa risposta. Se sei interessato, mandami un messaggio e te lo mando.

Ciao, Frank