【问题标题】:Oracle Java: Error casting java.sql.Blob datatype to Oracle BLOB datatypeOracle Java:将 java.sql.Blob 数据类型转换为 Oracle BLOB 数据类型时出错
【发布时间】:2019-02-02 00:26:26
【问题描述】:

在执行接受并返回 BLOB 数据的 Oracle Java 过程时出现以下错误,

错误报告 - ORA-00932:不一致的数据类型:预期返回 值,它是用户定义的 Java 类的实例,可转换为 Oracle 类型得到一个无法转换的对象 ORA-06512: 在 “”,第 86 行 ORA-06512:第 7 行 00932. 00000 - “不一致的数据类型:预期的 %s 得到了 %s” *原因:
*行动:

Java 代码

public static java.sql.Blob Convert_Image(java.sql.Blob srcBlob) {

java.sql.Blob desBlob = null;

try {
    Document document = new Document();

    ByteArrayOutputStream pdfDocumentOutputStream = new ByteArrayOutputStream();
    PdfWriter pdfDocumentWriter = PdfWriter.getInstance(document, pdfDocumentOutputStream);                        
    document.open();

    if (document.newPage()) {

        int indentation = 0;
        Image img = Image.getInstance(srcBlob.getBytes(1, (int) srcBlob.length()));
        float scaler = document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - indentation;
        img.scalePercent((scaler / img.getWidth()) * 100);

        document.newPage();
        document.add(Image.getInstance(img));
        document.close();

        desBlob = new SerialBlob(pdfDocumentOutputStream.toByteArray());

        pdfDocumentWriter.close();
        pdfDocumentOutputStream.close();

    }   
}
catch (Exception e) {
    Show_Message(e);
}

return desBlob;

}

Oracle 代码

FUNCTION CONVERT_IMAGE(
    P_BLOB IN DOCUMENTS.BLOB_CONTENT%TYPE)
  RETURN BLOB
AS
  LANGUAGE JAVA NAME 'egift.Util.Convert_Image (java.sql.Blob) return java.sql.Blob';  

触发器实现

...
DECLARE

    v_blob_content DOCUMENTS.BLOB_CONTENT%TYPE;

BEGIN

    IF :NEW.BLOB_CONTENT IS NOT NULL AND 
      (
        NVL(:NEW.MIME_TYPE,'#') = 'image/png' OR 
        NVL(:NEW.MIME_TYPE,'#') = 'image/jpeg' OR 
        NVL(:NEW.MIME_TYPE,'#') = 'image/gif' OR
        NVL(:NEW.MIME_TYPE,'#') = 'image/tiff' OR
        NVL(:NEW.MIME_TYPE,'#') = 'image/bmp'
      ) THEN
      v_blob_content := EGIFT_UTIL.CONVERT_IMAGE(:NEW.BLOB_CONTENT);
      IF v_blob_content is not null then
        :NEW.BLOB_CONTENT := v_blob_content;  
        :NEW.MIME_TYPE := 'application/pdf';
        :NEW.NAME := substr(:NEW.NAME,0,instr(:NEW.NAME,'.',-1)) || 'pdf';
      END IF;
    END IF;
...

【问题讨论】:

  • 所显示的代码都不会抛出异常并出现错误。请显示导致错误的实际代码。
  • 仅供参考: 不需要使用Blob,反正你只是要使用一个字节数组。使用字节数组。
  • 请显示异常的(完整)堆栈跟踪。
  • @Andreas 是的,看起来一切都很好,但并不是因为它引发了运行时错误。我认为 Oracle 无法将数据类型 java.sql.Blob 的返回值转换为 Oracle BLOB 数据类型。您提到了使用字节数组,您能否提供一个示例来详细说明。
  • 嗨@kapiell,一旦我在将 Blob 转换为 java.sql.Blob 时遇到问题。我使用 oracle.sql.BLOB 而不是这个类。不幸的是,我没有 Oracle 实例来测试解决方案。可以请你自己检查一下吗?

标签: java oracle java-7 oracle12c


【解决方案1】:

您需要从 Java 过程返回 oracle.sql.BLOBoracle.jdbc2.Blob 的实例,以便创建调用 Java 过程并返回 BLOB 的触发器。 ORACLE 实际上有一个表,他们将数据类型与他们可以接受的 Java 实例进行比较:

the legal data type mappings. Oracle Database converts between the SQL types and Java classes automatically

更新 1: 我实际上测试了传递 java.sql.Blob 并在函数中返回相同的类型,它按预期工作:

CREATE OR REPLACE AND RESOLVE JAVA SOURCE NAMED "Util" as
public class Util {
  public static java.sql.Blob Convert_Image(java.sql.Blob srcBlob) {

    return srcBlob;

    }
}
/

CREATE OR REPLACE FUNCTION CONVERT_IMAGE(
    P_BLOB BLOB)
  RETURN BLOB
AS
  LANGUAGE JAVA NAME 'Util.Convert_Image (java.sql.Blob) return java.sql.Blob';


select utl_raw.cast_to_varchar2(convert_image(utl_raw.cast_to_raw('test'))) from dual;
-- test

你可以尝试运行上面的代码,看看你是否得到同样的错误?

【讨论】:

    【解决方案2】:

    这是我实施的一个临时解决方案,因为我接近截止日期,我仍在寻找一个解决方案,我不必使用已弃用的类并希望避免引用 oracle.sql.BLOB并使用 java.sql.Blob。

    解决方法是创建一个 oracle.sql.BLOB 对象而不是 SerialBlob,然后从输出流中填充 bytearray,如下所示,

    conn = new OracleDriver().defaultConnection();
    desBlob = BLOB.createTemporary(conn, false, BLOB.DURATION_SESSION);
    desBlob.setBytes(1, pdfDocumentOutputStream.toByteArray());
    

    并使用抑制弃用警告,

    @SuppressWarnings("deprecation")
    

    最终的 Java 代码

    @SuppressWarnings("deprecation")
    public static java.sql.Blob Convert_Image(java.sql.Blob srcBlob) {
    
        java.sql.Blob desBlob = null;
    
        try {
            Document document = new Document();
    
            ByteArrayOutputStream pdfDocumentOutputStream = new ByteArrayOutputStream();
            PdfWriter pdfDocumentWriter = PdfWriter.getInstance(document, pdfDocumentOutputStream);
            document.open();
    
            if (document.newPage()) {
    
                int indentation = 0;
                Image img = Image.getInstance(srcBlob.getBytes(1, (int) srcBlob.length()));
                float scaler =
                    document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - indentation;
                img.scalePercent((scaler / img.getWidth()) * 100);
    
                document.newPage();
                document.add(Image.getInstance(img));
                document.close();
    
                //desBlob = new SerialBlob(pdfDocumentOutputStream.toByteArray());
                conn = new OracleDriver().defaultConnection();
                desBlob = BLOB.createTemporary(conn, false, BLOB.DURATION_SESSION);
                desBlob.setBytes(1, pdfDocumentOutputStream.toByteArray());
    
                pdfDocumentWriter.close();
                pdfDocumentOutputStream.close();
    
            }
        } catch (Exception e) {
            Show_Message(e);
        }
        return desBlob;
    
    }
    

    我已经设置了一个赏金来获得一个解决方案来解决这个问题而不使用不推荐使用的类,但我找不到一个,尽管我收到了这个问题的关注。在我找到正确的解决方案之前,这对我来说是一个悬而未决的问题。感谢所有努力的人。

    问候!

    【讨论】:

      【解决方案3】:

      我找到了这个没有弃用代码的解决方案:

          public static Blob bytes2Blob(byte[] b) throws Exception {
              if (System.getProperty("oracle.server.version") != null) {
                  Connection con = DriverManager.getConnection("jdbc:default:connection");
                  CallableStatement cStmt = con.prepareCall ("{ call DBMS_LOB.createtemporary(?,true,DBMS_LOB.SESSION) }");
                  cStmt.registerOutParameter(1, OracleTypes.BLOB);
                  cStmt.execute();
                  Blob blob = ((OracleCallableStatement)cStmt).getBLOB(1);
                  cStmt.close();
                  OutputStream out = blob.setBinaryStream(1L);
                  out.write(b);
                  out.flush();
                  return blob;
              } else {
                  return new javax.sql.rowset.serial.SerialBlob(b);
              }
      

      【讨论】:

        猜你喜欢
        • 2021-03-02
        • 1970-01-01
        • 2013-05-09
        • 2016-02-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-30
        相关资源
        最近更新 更多