无法使用 Hibernate/PostgreSQL 将欧洲符号存储到 LOB 字符串属性中

2023-11-21

我在使用 Hibernate 3.6.10 的 PostgreSQL 8.4 中将特殊字符(如欧元符号 (€))写入和读回 LOB 字符串属性时遇到问题。

我所知道的是,PostgreSQL 提供了两种不同的方法来在表的列中存储大字符对象。它们可以直接存储到该表列中,也可以间接存储到单独的表中(实际上称为 pg_largeobject)。在后一种情况下,该列保存对 pg_largeobject 中的行的引用(OID)。

Hibernate 3.6.10 中的默认行为是间接 OID 方法。但是,可以向 Lob 属性添加额外的注释 @org.hibernate.annotations.Type(type="org.hibernate.type.TextType") 以获得直接存储行为。

两种方法都工作得很好,除了我想使用欧元符号 (€) 等特殊字符的那一刻。在这种情况下,直接存储机制继续工作,但间接存储机制中断。

我想用一个例子来证明这一点。我创建了一个具有 2 个 @Lob 属性的测试实体。一种遵循直接存储原则,另一种遵循间接存储原则:

@Basic
@Lob
@Column(name = "CLOB_VALUE_INDIRECT_STORAGE", length = 2147483647)
public String getClobValueIndirectStorage()

and

@Basic
@Lob
@org.hibernate.annotations.Type(type="org.hibernate.type.TextType")
@Column(name = "CLOB_VALUE_DIRECT_STORAGE", length = 2147483647)
public String getClobValueDirectStorage()

如果我创建一个实体,用欧元符号填充两个属性,然后将其保留到数据库中,当我执行 SELECT 时,我会看到以下内容

 id | clob_value_direct_storage | clob_value_indirect_storage
----+---------------------------+----------------------------
  6 | €                         | 910579                     

如果我随后查询表 pg_largeobject 我会看到:

  loid  | pageno | data
--------+--------+------
 910579 |      0 | \254

pg_largeobject 的“data”列是 bytea 类型,这意味着信息存储为原始字节。表达式“\254”表示一个字节,在 UTF-8 中表示字符“Ø”。这正是我从数据库加载实体时得到的值。

UTF-8 中的欧元符号由 3 个字节组成,因此我预计“数据”列有 3 个字节而不是 1 个字节。

这不仅发生在欧元符号上,而且发生在许多特殊字符上。这是休眠中的问题吗?或者 JDBC 驱动程序?有什么办法可以调整这种行为吗?

提前致谢,
亲切的问候,
弗兰克·德布鲁因


在深入研究 Hibernate 和 PostgreSQL JDBC 驱动程序的源代码后,我设法找到了问题的根本原因。最后调用BlobOutputStream(由JDBC驱动程序提供)的write()方法将Clob的内容写入数据库。这个方法看起来像这样:

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

此方法采用“int”(32 位/4 字节)作为参数,并将其转换为“byte”(8 位/1 字节),从而有效地丢失 3 个字节的信息。 Java 中的字符串表示形式采用 UTF-16 编码,这意味着每个字符由 16 位/2 个字节表示。欧洲符号的 int 值是 8364。转换为字节后,值 172 仍然存在(以八位字节表示形式 254)。

我不确定现在解决这个问题的最佳方案是什么。恕我直言,JDBC 驱动程序应该负责将 Java UTF-16 字符编码/解码为数据库需要的任何编码。但是,我在 JDBC 驱动程序代码中看不到任何调整其行为的可能性(并且我不想编写和维护我自己的 JDBC 驱动程序代码)。

因此,我使用自定义 ClobType 扩展了 Hibernate,并设法在写入数据库之前将 UTF-16 字符转换为 UTF-8,在检索 Clob 时反之亦然。

解决方案太大,无法简单粘贴到此答案中。如果您有兴趣,请给我留言,我将其发送给您。

干杯, 弗兰克

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 Hibernate/PostgreSQL 将欧洲符号存储到 LOB 字符串属性中 的相关文章

随机推荐

  • Xcode 4.2 iOS 5:来自 UITableView 的多个 Segues

    我现在开始使用适用于 iOS5 的 Xcode 4 2 有一些更改 我现在遇到一个问题 我无法找到解决方法 我正在使用 UITablwView 做一个示例 该视图以编程方式填充了 2 个部分 第 1 部分仅包含 1 行 第 2 部分包含 3
  • 访问Linux /dev/USB作为标准文件与USB设备通信

    我正在研究在 Linux 中与 USB 设备通信的方法 并且不想编写 Linux 内核驱动程序 我知道 libusb 存在并且是一个可以工作的用户空间库 但是我们的嵌入式设备不支持 usbfs 并且更改内核以添加支持确实很痛苦 所以我的问题
  • iOS13 模拟器上的 UIDocumentBrowserViewController 错误“无法为 url 创建 urlWrapper”

    我有一个非常奇怪的问题UIDocumentBrowserViewController在 iOS 13 上测试时 importHandler newDocumentURL move 似乎没有任何原因崩溃 DocumentManager Can
  • 为什么Lucene在索引大文件时会导致OOM?

    我正在使用 Lucene 2 4 0 和 JVM JDK 1 6 0 07 我不断收到OutOfMemoryError Java heap space 当尝试索引大型文本文件时 示例 1 对 5 MB 文本文件建立索引会导致内存不足 最大容
  • 模拟文本输入字段上的退格键

    有人可以提供一个很好的例子来模拟退格键 on a
  • 更改java控制台输出的颜色

    我想知道是否有什么办法可以设置我在 Java 中输出到控制台的文本的颜色 是否特定于系统并不重要 因为该程序只能在我的 Windows 7 x64 笔记本电脑上运行 这个问题 在 java eclipse 控制台中更改颜色几周前被问到 并且
  • 写入Main Bundle 目录。允许吗?

    我非常确定在 iOS 中不可能在主 Bundle 中写入 例如如下操作 NSString path NSBundle mainBundle pathForResource Data ofType plist something xmlDat
  • Three.js 截图

    我需要制作网站的屏幕截图 我尝试使用 html2canvas 和所有它的工作 但问题是我正在使用 THREE WebGLRenderer 和 THREE CSS3DRenderer 用于 webgl 中的 html 所以当我制作屏幕截图时
  • 如何为相同大小分区的 Spark RDD 定义自定义分区器,其中每个分区具有相同数量的元素?

    我是 Spark 新手 我有一个大型元素数据集 RDD 我想将其划分为两个大小完全相同的分区 以保持元素的顺序 我尝试使用RangePartitioner like var data partitionedFile partitionBy
  • 序列化有时是数组的 Json 属性[重复]

    这个问题在这里已经有答案了 有没有什么方法可以在一次操作中序列化从十进制到十进制 的 Json 对象属性 在我的 Json 产品提要中 特价商品表示为数组 正常价格 促销价格 普通商品只是价格 就像这样 product umbrella p
  • C++ 未处理的异常

    如果发生未处理的异常 C 是否提供了一种 显示 可视化内容的方法 我想做的是做一些像assert unhandled exception msg 如果它确实发生 如下面的示例所示 include
  • Android 未解决的主机异常

    我尝试使用以下方法从 Android 应用程序调用 RESTful Web 服务 HttpHost target new HttpHost http ServiceWrapper SERVER HOST ServiceWrapper SER
  • Git 哈希值是如何计算的?

    我试图了解 Git 如何计算 refs 的哈希值 git ls remote https github com git git 29932f3915935d773dc8d52c292cadd81c81071d refs tags v2 4
  • 如何在 Qt 中通过以太网播放流媒体音频?

    我的目标是通过 LAN 网络无延迟或最少延迟地传输 wav 文件 我们还按部分读取服务器计算机上的文件 均为 320 字节 之后我们通过 UDP 发送数据包并将接收写入 jitter buffer 中 抖动缓冲区的大小为 10 为了获得清晰
  • 部署带有嵌入式sqlite的winform应用程序

    我正在部署一个使用 vs 2008 0n XP sp3 构建的 winform 应用程序 我创建了一个带有空架构的数据库 将其放入项目的根文件夹和我选择的属性中Build Action 嵌入式资源 and Copy to Output di
  • iPhone:安装 SSL 连接证书

    我希望我的应用程序在设备上安装 SSL 证书 使其能够访问我的 https 网站 任何建议将不胜感激 谢谢 我发现最好的方法是执行以下操作 1 使用桌面浏览器将证书保存到本地 2 给自己写一封电子邮件 并将证书作为附件 3 在您的 iOS
  • 用于新闻源的 Firebase 扇出结构

    我有一个数据库posts users以及其他节点 例如经典的社交媒体应用程序 我正在继续对我的应用程序实施最佳实践 现在我想重写我的新闻报道 我关注的用户帖子 如 Instagram 中的主页选项卡 我读过一些关于fan out策略 现在我
  • 如何使用 CarrierWave 从 S3 获取真实文件

    我有一个读取文件内容并为其建立索引的应用程序 我将它们存储在磁盘本身中 但现在我使用 Amazon S3 因此以下方法不再有效 事情是这样的 def perform docId document Document find docId if
  • 声明与 TypeScript 一起使用的 JS 库

    有很多类似问题的线程 但据我所知 这个线程是独一无二的 我在用着jQuery 地址插件在我的应用程序中 并想在 TypeScript 文件中使用它 不幸的是 这儿没有绝对打字可用于库的脚本 当我尝试使用 jQuery address 时 我
  • 无法使用 Hibernate/PostgreSQL 将欧洲符号存储到 LOB 字符串属性中

    我在使用 Hibernate 3 6 10 的 PostgreSQL 8 4 中将特殊字符 如欧元符号 写入和读回 LOB 字符串属性时遇到问题 我所知道的是 PostgreSQL 提供了两种不同的方法来在表的列中存储大字符对象 它们可以直