Cannot store Euro-sign into LOB String property with Hibernate/PostgreSQL

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-30 18:28:13

After a lot of digging around in the source code of Hibernate and the PostgreSQL JDBC driver I managed to find the root cause of the problem. In the end the write() method of the BlobOutputStream (provided by the JDBC driver) is invoked to write the contents of the Clob into the database. This method looks like this:

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

This method takes an 'int' (32 bits/4 bytes) as argument and converts it to a 'byte' (8 bits/1 byte) effectively losing 3 bytes of information. String representations within Java are UTF-16 encoded, meaning that each character is represented by 16 bits/2 bytes. The Euro-sign has the int value 8364. After conversion to byte, the value 172 remains (in octet representation 254).

I am not sure what now the best resolution is to this problem. IMHO the JDBC driver should be responsible for encoding/decoding the Java UTF-16 characters to whatever encoding the database needs. However, I do not see any tweaking possibilities in the JDBC driver code to alter its behaviour (and I do not want to write and maintain my own JDBC driver code).

Therefore, I extended Hibernate with a custom ClobType and managed to convert the UTF-16 characters to UTF-8 before writing to the database and vice-versa when retrieving the Clob.

The solutions is too large to just simple paste in this answer. If you are interested, drop me a line, and I send it to you.

Cheers, Franck

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!