从blob反序列化java对象

时间:2013-02-08 08:24:28

标签: java oracle oracle11g blob deserialization

something i got from developers

首先,我道歉,我将要问一些愚蠢的问题。我不知道java AT ALL,我不知道是否允许我们提出这样的问题。

如果没有 - 删除我的主题。

oracle中有一个存储blob的表。它是二进制的,我能够解码它,输出看起来像这样

¬í sr /com.epam.insure.credentialing.forms.StorageBeanÀÓ ¯w/§ L     variablest Ljava/util/Map;xpsr java.util.HashMapÚÁÃ`Ñ F 
loadFactorI     thresholdxp?@     w      t $_hasCompletedt  t 
$_wf_progresssr java.lang.Integerâ ¤÷‡8 I valuexr java.lang.Number†¬•”à‹  xp   t $_wf_statussq ~    t $_form_instance_idsr java.lang.Long;‹äÌ#ß J valuexq ~          ‹©t $_isVisitedt truet 1sq ~  sq ~ ?@     `w   €   _t  confidential readable infot 1t confidential readable infot $_errorssr java.util.ArrayListxÒ™Ça I sizexp    w   
xt regionIdsq ~       ët 
confidential readable infot t  t $_subbean_errorssq ~     w   
xt regiont  SOUTHWESTt idt  t codet  t reqTypeNamet 
confidential readable infot t confidential readable infot tint  t $_hasCompletedt falset comRequiredt  t 
lineImpactq ~ t prChiropractorsq ~ t fromTypeReqt not zipt 342t changeToTypeReq6t confidential readable infot t 
prPodiatristsq ~ t 
$_isValidatedt truet $_hasErrorsq ~ -t EVPapprovalsq ~  sq ~ ?@     w   Approvedq ~ Ct 
NEGOTIATORq ~ Et 
Negotiatort datet 
03/31/2006q ~ It confidential readable infot q ~ \xt updateRequiredt noq ~ t truet  approverssr .forms.StorageBeanList«WtúœG  xq ~    w   
q ~ Rsq ~  sq ~ ?@     w      t commentst  t decisiont Approvedq ~ Ct RVPq ~ Et RVPt datet 
04/04/2006q ~ It t commentst  t decisiont Approvedq ~ Ct COOq ~ Et COOt datet 
04/14/2006q ~ It ~ †xsq ~  sq ~ ?@     w      t commentsq ~ Pt decisiont Approvedq ~ Ct CEOq ~ Et CEOt d

所以这是我的问题

  1. 由于某种原因,当我尝试将解码的blob值(我上面发布的内容)插入表格时(我打算将其移动到MS Access并在那里解析它。这将是一个可怕的解决方案,但我很绝望) - 唯一插入的是没有引号的“¬í”。此外,我无法选择所有并从DBMS输出窗口复制它,再次,唯一粘贴的是没有引号的“¬í”。似乎这个文本并不存在。有没有人知道如何将其插入表中?

  2. 如果我以正确的方式做到并使用java,我从哪里开始?原谅这种愚蠢,但我甚至不知道如何运行java代码。我在网上找到了一些示例代码,但我不知道在哪里粘贴它:)

  3. 我确实google了,看到我必须在文本编辑器中创建一个.java文件然后编译它,这对我的情况是否正确?我想也许这是一些不同的java代码,我想也许在我的情况下我必须从oracle运行它,因为那是表的位置。

    我也有桌子结构,我附上了一块。这个blob存储了一个表。

    无论如何,我确信现在很明显我一无所知。如果有人能指出某个地方,我真的很感激。

    谢谢

2 个答案:

答案 0 :(得分:3)

这是一个oracle 11g java存储函数的示例,它从blob反序列化java对象。作为免费奖金添加了一个oracle java存储过程的示例,用于更新带有序列化java对象的blob。

如果object的类不是java内置的(在我的例子中),你还需要在oracle数据库中publish它的源代码(带有所有依赖项)。

CREATE OR REPLACE JAVA SOURCE NAMED "ServiceParamsBLOBHandler" AS
import java.io.*;
import java.util.*;
public class ServiceParamsBLOBHandler {

    private static Object deserialize(InputStream stream) throws Exception {

        ObjectInputStream ois = new ObjectInputStream(stream);
        try {
            return ois.readObject();
        } finally {
            ois.close();
        }
    }

    private static byte[] serialize(Object object) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.close();
        return baos.toByteArray();
    }

    //@SuppressWarnings("unchecked")
    private static List<Map<String, String>> getParams(oracle.sql.BLOB blob) throws Exception {
        return (List<Map<String, String>>) deserialize(blob.getBinaryStream());
    }

    public static oracle.sql.BLOB updatedParamField(oracle.sql.BLOB blob, String paramName, String fieldName, String value)
            throws Exception {

        List<Map<String, String>> params = getParams(blob);
        Map<String, String> param = getParam(params, paramName);
        param.put(fieldName, value);
        oracle.sql.BLOB res = oracle.sql.BLOB.createTemporary(blob.getOracleConnection(), true, oracle.sql.BLOB.DURATION_CALL);
        res.setBytes(1, serialize(params));
        return res;
    }

    public static void updateParamField(oracle.sql.BLOB[] blobs, String paramName, String fieldName, String value)
            throws Exception {

        oracle.sql.BLOB blob = blobs[0];
        List<Map<String, String>> params = getParams(blob);
        Map<String, String> param = getParam(params, paramName);
        param.put(fieldName, value);
        blob.truncate(0);
        blob.setBytes(1, serialize(params));
    }

    private static Map<String, String> getParam(List<Map<String, String>> params, String name) {
        for (Map<String, String> param : params) {
            if (name.equals(param.get("name"))) {
                return param;
            }
        }
        return null;
    }

    public static String getParamField(oracle.sql.BLOB blob, String paramName, String fieldName) throws Exception {
        Map<String, String> param = getParam(getParams(blob), paramName);
        return param == null ? null : param.get(fieldName);
    }

}
/

alter java source "ServiceParamsBLOBHandler" compile
--select * from SYS.USER_ERRORS
/

CREATE OR REPLACE function getServiceParamField(b IN BLOB, paramName IN VARCHAR2, fieldName IN VARCHAR2) RETURN VARCHAR2
as LANGUAGE JAVA NAME 'ServiceParamsBLOBHandler.getParamField(oracle.sql.BLOB, java.lang.String, java.lang.String) return String';
/

CREATE OR REPLACE function updatedServiceParamField(b IN BLOB, paramName IN VARCHAR2, fieldName IN VARCHAR2, value IN VARCHAR2) RETURN BLOB
as LANGUAGE JAVA NAME 'ServiceParamsBLOBHandler.updatedParamField(oracle.sql.BLOB, java.lang.String, java.lang.String, java.lang.String) return oracle.sql.BLOB';
/

CREATE OR REPLACE PROCEDURE updateServiceParamField(b IN OUT BLOB, paramName IN VARCHAR2, fieldName IN VARCHAR2, value IN VARCHAR2)
AS LANGUAGE JAVA NAME 'ServiceParamsBLOBHandler.updateParamField(oracle.sql.BLOB[], java.lang.String, java.lang.String, java.lang.String)';
/

-- oracle blob read usage example:
select getServiceParamField(byte_value, 'account', 'format') from entity_property where name='params';

-- oracle blob update with java stored function usage example:
update entity_property set byte_value=updatedServiceParamField(byte_value, 'account', 'format', '15')
where name='params' and entity_id = 123

-- oracle blob update with java stored procedure usage example:
BEGIN
   FOR c IN (select byte_value from entity_property where name='params' and entity_id = 123 for update) LOOP
       updateServiceParamField(c.byte_value, 'account', 'format', '13');
   END LOOP;
END;
/

<强>更新

有关案件的具体摘要。

1)完整对象加载

    private static String getVariable(oracle.sql.BLOB blob, String name) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(blob.getBinaryStream());
        try {
            //noinspection unchecked
            return ((HashMap<String, String>) ((StorageBean) ois.readObject()).variables).get(name);
        } finally {
            ois.close();
        }
    }

2)部分字段加载

    private static String getVariable(oracle.sql.BLOB blob, String name) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(blob.getBinaryStream());
        try {
            ois.skipBytes(variablesOffset);
            //noinspection unchecked
            return ((HashMap<String, String>) ois.readObject()).get(name);
        } finally {
            ois.close();
        }
    }

答案 1 :(得分:1)

我会在某些时候学会在java中这样做,但由于这是一个匆忙 - 我决定使用SQL从blob中提取字段。我把它放在这里以防万一其他人非常渴望这样做。

这是一个非常丑陋和缓慢的解决方案,但到目前为止,我能够得到一些领域。一旦我完成,我会更新,说我是否能够得到所有东西。

这是我正在使用的代码(这仅适用于1个字段,但它会给你一个想法)

    DECLARE
     CURSOR c_dts IS
       SELECT Form_ID
         FROM NR_DTS_FORMTABLE
        WHERE   1 = 1
           --AND ROWNUM BETWEEN 501 AND 4500
           AND form_ID > 204815
           --AND ROWNUM < 5000
           AND ROWNUM < 3
           --AND form_id IN (SELECT form_id FROM NR_DTS_BLOB)
           AND Form_Type_ID = 102;
     DTS c_dts%ROWTYPE;
BEGIN
     OPEN c_dts;
     LOOP
       FETCH c_dts INTO DTS;
       EXIT WHEN c_dts%NOTFOUND;
       DECLARE
         v_hold_blob BLOB;
         v_len NUMBER;
         v_raw_chunk RAW(10000);
         v_chr_string VARCHAR2(32767);
         -- v_chr_string CLOB;
         v_position NUMBER;
         c_chunk_len NUMBER := 1;
         Form_ID NUMBER;
       BEGIN
         SELECT form_content
           INTO v_hold_blob
           FROM NR_DTS_FORMTABLE
          WHERE Form_ID = DTS.Form_ID;
         v_len := DBMS_LOB.getlength(v_hold_blob);
         v_position := 1;
         WHILE (v_position <= LEAST(v_len, 32767)) LOOP
              v_raw_chunk := DBMS_LOB.SUBSTR(v_hold_blob, c_chunk_len, v_position);
              v_chr_string := v_chr_string || CHR(hex_to_decimal(RAWTOHEX(v_raw_chunk)));
              v_position := v_position + c_chunk_len;
         END LOOP;

         --insert into table
         INSERT INTO NR_DTS_BLOBFIELDS_VARCHAR(formid
                               ,regionId)
              SELECT DTS.Form_ID
                 ,SUBSTR(v_chr_string
                     ,INSTR(v_chr_string, 'regionIdt') + LENGTH('regionIdt') + 2
                     ,INSTR((SUBSTR(v_chr_string, INSTR(v_chr_string, 'regionIdt') + LENGTH('regionIdt') + 2))
                        ,CHR(116) || CHR(0)))
                    regionId
             FROM DUAL;
       END;
     --  DBMS_OUTPUT.put_line(DTS.Form_ID);
     END LOOP;
     CLOSE c_dts;
END;