PostgreSQL插入问号而不是unicode字符

时间:2014-12-04 16:17:33

标签: java postgresql jdbc unicode

每当通过我的应用程序进行插入时,所有Unicode字符(无论是日语,希腊语等)都会被问号替换。

SAVEPOINT "DAO"
LOG:  execute <unnamed>: insert into foo values ($1,$2,$3)
DETAIL:  parameters: $1 = '23', $2 = '34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37', $3 = 'Anyone-日本語_l'

从上面的日志条目中可以看出,数据库接受正确的Unicode参数。

但是,插入后,表条目如下所示:

23 | 34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37 | Anyone-???_l

我的第一个猜测是这是一个数据库配置问题,但我已经确认(据我所知)Postgres确实通过执行以下操作来接受UTF-8:

SHOW server_encoding;
server_encoding
-----------------
UTF8
(1 row)

SHOW client_encoding;
client_encoding
-----------------
UTF8
(1 row)

我还通过手动将条目插入数据库来进一步证实这一点:

INSERT INTO foo values(25, ‘the_id’, ‘ΑΒΓΔΕΖΗΘ’);
INSERT 0 1
25 | the_id | ΑΒΓΔΕΖΗΘ

从上面可以理解,数据库已经接受了我的值,并成功地将Unicode字符添加到数据库中。

此时,我认为当这些值从我的应用程序推送到JDBC连接器并进入数据库时​​会出现问题。我想也许需要告诉JDBC连接器它将传输Unicode数据。确实有一种方法可以做到这一点,方法是在JDBC连接器的URL中附加以下内容:

jdbc:postgresql://localhost/bar?useUnicode=yes&characterEncoding=UTF-8

不幸的是,上述情况没有任何区别。

我已经排除了应用程序的代码,因为它是一个非常大的项目的一部分,相关的部分在这里和那里都是分散的。但是,我认为它们与问题无关,因为Postgres日志清楚地显示了它收到的参数。

数据库接收的查询和unicode数据是否正确,导致此问题的原因是什么?

OS: RHEL 6.6
Postgres version: 9.3.5
JDBC Connector: Tried a couple (8.1, 9.3)
JRE: 1.7

数据库确实期待UTF-8:

psql -U postgres -h localhost --list

Name      |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
----------------+----------+----------+-------------+-------------+--------------
bar       | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |

相关条目的 bytea 结果如下:

SELECT foo_name::bytea FROM foo;

foo_name
--------------------------
\x416e796f6e652d3f3f3f5f6c

问号实际上已插入数据库中:

SELECT * FROM foo WHERE foo_name LIKE 'Anyone-?%'
23 | 34bcb5f2-e7ee-40cf-9103-f2d1bf2ac7acd853d7c6-1703-44d2-aa99-6fd1df84da37 | Anyone-???_l

我还抓住了我的一个测试的字节序列,这个测试是在JDBC控制器被送到PGStream之前由JDBC控制器生成的。

{65, 110, 121, 111, 110, 101, 45, -26, -105, -91, -26, -100, -84, -24, -86, -98, 95, 105}

我已通过执行以下操作(在独立应用程序中)将其转换为UTF-8字符串:

String result = new String(bytes, StandardCharsets.UTF_8);

结果是正确的:任何人 - 日本语_i

2 个答案:

答案 0 :(得分:3)

在深入研究遗留代码后,我发现并修复了问题。

数据库层运行得很好;当系统尝试使用ByteArrayInputStream将相同的值重新插入数据库时​​出现问题。

通过在包含 foo_name 的String中执行getBytes()来填充ByteArrayInputStream。但是,在调用此方法时应定义UTF-8编码。

通过更改:

String name = "日本語";
InputStream is = new ByteArrayInputStream(name.getBytes());

为:

String name = "日本語";
InputStream is = new ByteArrayInputStream(name.getBytes(StandardCharsets.UTF_8));

问题已解决。

答案 1 :(得分:1)

我遇到了unicode-8的问题,有postgres和glassfish。我在persistence.xml中试过这个并修复了。我希望它可以帮到你

<properties>
  <property name="javax.persistence.jdbc.url"
           value="jdbc:postgresql://(url_Project)?useUnicode=yes"/>
</properties>

(url_Proyecto)是数据库的完整网址