每当通过我的应用程序进行插入时,所有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
答案 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)是数据库的完整网址