【问题标题】:How to convert a CLOB data type to a String in Hibernate?如何在 Hibernate 中将 CLOB 数据类型转换为字符串?
【发布时间】:2025-12-02 02:45:02
【问题描述】:

在hibernate(3.2.1.GA)中,我使用以下方法将CLOB类型的数据插入到Oracle(10g)数据库中。

Hibernate.createClob(parameters.get("txtCatImage"));

parameters 是一个Map,其中存储了所有请求参数。在直接从数据库中检索Clob 数据类型时,类似entityObj.getCatImage() 的东西不起作用。

看到thisthis 的问题,但找不到方法。

以下是使用Clob 类型属性的实体。

public class Category  implements java.io.Serializable {

    private Long catId; // Primary key.
    private Clob catImage; // CLOB type field.
    // Other fields.
    private static final long serialVersionUID = 1L;

    public Category() {}

    // Overloaded constructs + getters + setters + hashcode() + equals() + toString().
}

在本例中,数据库中的Clob 字段只存储了一个图像文件名。

【问题讨论】:

  • 定义“不起作用”。您收到错误还是返回null
  • @Dev - 它没有给出任何错误。它只是用obj.getCatImage().toString()obj.getCatImage() 显示类似org.hibernate.lob.SerializableClob@1e2ad75 的对象引用,而不是显示作为Oracle 数据库中图像文件名的实际内容。 Oracle 提示符上的实际 SQL 如 SELECT * FROM category 但是直接在 Oracle 终端上显示实际内容。

标签: spring hibernate oracle10g clob


【解决方案1】:

使用适当的参数调用Clob.getSubString(long, int) 以获得所需的String 或使用Clob.getAsciiStream()Clob.getCharacterStream() 将Clob 读取为InputStream 或Reader。

如果 Clob 的字符数少于 2147483647(又名Integer.MAX_VALUE),您可以这样做

Clob clob = ... //Your clob
String clobString = clob.getSubString(0, clob.length());

【讨论】:

  • getSubString(): 第一个字符在位置 1,而不是 0,奇怪的是,但这就是 JavaDoc 所说的
  • 在早期版本中,位置可能从 0 开始。另外,两个参数都必须是 int (clob.length() 返回 long,所以你也需要转换它)。
【解决方案2】:

Dev(见上文)使用“Clob.getSubString(long, int)”的解决方案将消耗大量内存。 我更喜欢以下解决方案。

private static String getAsString(Clob clob) {
    Reader reader = null;
    BufferedReader bufferedReader = null;
    try {
        reader = clob.getCharacterStream();
        bufferedReader = new BufferedReader(reader);
        return IOUtils.toString(bufferedReader);

    } catch (Exception e) {
        throw new RuntimeException("Error while reading String from CLOB", e);
    } finally {
        IOUtils.closeQuietly(reader);
        IOUtils.closeQuietly(bufferedReader);
    }
}

【讨论】:

    【解决方案3】:

    这可能有效

    new BufferedReader(new InputStreamReader(catImage.getAsciiStream())).readLine()
    

    【讨论】:

      【解决方案4】:

      正如 Alex 所说,clob.getSubString(0, clob.length()) 也会消耗内存并且性能不佳。 我遇到了同样的问题,我正在从数据库中获取一个巨大长度的 varchar2(2000-4000 ) 数据字段。由于这个 varchar 字段,性能下降到 1 分 20 秒。从数据库到实体类的获取速度很快,但是从实体复制到 SO 对象(或 POJO)需要大量时间。

      我正在使用 JPA 获取数据库数据。 我保存为字符串的实体字段。 在 SO Object(POJO) 中,我将该字段类型设置为 CLOB 数据类型。

      从数据库中获取数据后,数据在实体对象中可用。 复制到 SO 对象(CLOB 类型),

      SOobject.setLongStringField( new SerialClob(entityString.toCharArray()));//Converting String to CLOB
      

      在 UI 级别,我的 SOobject,而不是普通的 getter setter 方法,我使用如下(Alex 的代码)

      public String getLongStringField() {
               Reader reader = null;
                  BufferedReader bufferedReader = null;
                  try {
                      reader = longStringField.getCharacterStream();
                      bufferedReader = new BufferedReader(reader);
                      return IOUtils.toString(bufferedReader);
      
                  } catch (Exception e) {
      
                      throw new RuntimeException("Error while reading String from CLOB", e);
                  } finally {
                      IOUtils.closeQuietly(reader);
                      IOUtils.closeQuietly(bufferedReader);
                  }
          }
      
          public void setLongStringField(Clob longStringField) {
              this.longStringField= longStringField;
          }
      

      希望对你有帮助!!!

      【讨论】:

        【解决方案5】:

        您可以使用它来阅读所有内容:

        new BufferedReader(new InputStreamReader(clob.getAsciiStream())).lines().collect(Collectors.joining());
        

        【讨论】: