[an error occurred while processing this directive] IT • archiv :: Print

IT • archiv


[an error occurred while processing this directive]

[an error occurred while processing this directive]

Использование Blob в интерфейсе SQLData для объектов Oracle

[an error occurred while processing this directive](none) [an error occurred while processing this directive](none)[an error occurred while processing this directive] ::
[an error occurred while processing this directive](none)
[an error occurred while processing this directive]([an error occurred while processing this directive] Вадим Земляной [an error occurred while processing this directive])

[an error occurred while processing this directive](none)
PDF versionPDF версия

Несколько странный способ, который описан в документации к Oracle, относительно работы с типами данных LOB, подтолкнул меня найти другой путь, который позволяет более красиво использовать Blob с JDBC.

Для того, чтобы записать содержимое в поле Blob, вам необходимо сначала получить ссылку на это поле — локатор.

В документации к Oracle для этого сначала вызывают инструкцию SELECT.

stmt.execute ("insert into my_blob_table
              values ('row1', empty_blob()");
BLOB blob;
   String cmd = "SELECT * FROM my_blob_table WHERE X='row1'";
   ResultSet rest = stmt.executeQuery(cmd);
   BLOB blob = ((OracleResultSet)rset).getBLOB(2);
   OutputStream outstream = blob.getBinaryOutputStream();
   outstream.write(….

Это не очень логично, что для того что бы вставить что-то в таблицу, нужно сначала из неё что то взять. Возможно инженеры из Oracle так шутят по поводу третьего закона Ньютона. Богам тоже нужен отдых. Но какая бы на то не была причина, этот способ не очень подходит для использования в объектах, реализующих интерфейс SQLData и содержащих BLOB. Обычно, когда Вы пишете такие объекты, Вы стремитесь к тому, что бы они были максимально независимы, и привязывать их к какой-либо таблице крайне нежелательно. Решением здесь может быть использование временных LOB (Temporary LOB).

Так как все мы любим примеры и не любим тратить время на копание в документации, я приведу пример реализации этого способа:

public class SQLObject implements SQLData{
    private String sql_type;
    private oracle.sql.BLOB content;
    public Object obj;
    private OracleCallableStatement close_st;

  public SQLObject() {
  }

  public SQLObject(String sql_type, Object obj,Connection conn)
                                               throws Exception {
    this.sql_type = sql_type;
    OracleCallableStatement open_st =
       (OracleCallableStatement) conn.prepareCall(
          "BEGIN
           DBMS_LOB.CREATETEMPORARY(:1,TRUE,DBMS_LOB.SESSION);
           DBMS_LOB.OPEN(:1,DBMS_LOB.LOB_READWRITE);
           END;");
    open_st.registerOutParameter(1,Types.BLOB);
    open_st.execute();
    close_st =
     (OracleCallableStatement)conn.prepareCall
               ("BEGIN DBMS_LOB.CLOSE(?); END;");
    content = open_st.getBLOB(1);
    java.io.OutputStream os = content.getBinaryOutputStream();
    java.io.ObjectOutputStream objs =
                           new java.io.ObjectOutputStream(os);
    objs.writeObject(obj);
    objs.flush();
    objs.close();
  }

  // define a get method to return the SQL type of the object
  public String getSQLTypeName() throws SQLException {
    return sql_type;
  }

  // define the required readSQL() method
  public void readSQL(SQLInput stream, String typeName)
                                       throws SQLException {
    sql_type = typeName;
    content = (BLOB)stream.readBlob();
    try{
      java.io.ObjectInputStream is =
        new java.io.ObjectInputStream(content.getBinaryStream());
      obj = is.readObject();
      is.close();
    }catch ( Exception e){
      throw new java.sql.SQLException(e.getMessage());
    }
  }

  // define the required writeSQL() method
  public void writeSQL(SQLOutput stream)  throws SQLException {
    try{
      stream.writeBlob(content);
    }catch ( Exception e){ }
    close_st.setBLOB(1, content);
    close_st.execute();
    close_st.close();
  }
  protected void  finalize() throws java.lang.Throwable{
    if ((close_st != null )&& !close_st.closed)
    try{
      close_st.setBLOB(1, content);
      close_st.execute();
      close_st.close();
    }catch ( Exception e){ }
    super.finalize();
  }
}
Класс для работы с таким объектом выглядит так :
public class OraObject {
  private PreparedStatement get_st;
  private PreparedStatement set_st;
  private final String get_str =
                    "SELECT cv FROM docs  WHERE ID=(0)" ;
  private final String set_str =
                    "INSERT into docs(cv,id) VALUES(?,0)" ;
  protected String url         =
                    "jdbc:oracle:thin:@your_host:1521:your_db" ;
  protected String user        ="you" ;
  protected String pass        ="your_password" ;


  public OraObject() {
    Connection conn = null;
    try{
       Class.forName("oracle.jdbc.driver.OracleDriver") ;
       Driver driver = DriverManager.getDriver( url ) ;
       conn = DriverManager.getConnection(url, user, pass);
       Map map = ((OracleConnection)conn).getTypeMap();
       map.put("CONTENT", Class.forName("test.db.SQLObject"));
       set_st = conn.prepareStatement(set_str);
       SQLObject sql_cv =
           new SQLObject("CONTENT",new String("1"),conn);
       SQLObject sql_cv1 =
           new SQLObject("CONTENT",new String("2"),conn);
       SQLObject[]  sql_vts =  {sql_cv,sql_cv1};
       ArrayDescriptor arraydesc =
           ArrayDescriptor.createDescriptor("CONTENTS", conn);
       Array array = new ARRAY(arraydesc, conn, sql_vts);
       set_st.setArray(1,array);
       set_st.execute();
       set_st.close();
       get_st = conn.prepareStatement(get_str);
       ResultSet rs = get_st.executeQuery();
       rs.next();
       ARRAY ar = ((OracleResultSet)rs).getARRAY(1);
       Object[] cv = (Object[]) ar.getArray();
       for (int i=0; i<cv.length; i++) {
         SQLObject variant = (SQLObject) cv[i];
         System.out.println(variant.obj.toString());
       }
       rs.close();
       get_st.close();
    }catch (Exception e){
      e.printStackTrace() ;
    }finally{
       try {
          if (conn != null) conn.close();
       }catch (Exception e){}
       System.exit(0);
    }
  }
   public static void main(String[] args) {
    OraObject oraObject = new OraObject();
  }
}

Здесь объект используется в массиве, но так же можно и обычным способом, используя setObject(). Скрипт для этого примера такой:

CREATE OR REPLACE TYPE content AS OBJECT(content BLOB);
CREATE OR REPLACE TYPE contents AS TABLE OF content;

DROP TABLE  docs;
CREATE TABLE docs
  (id NUMBER(11),
  cv contents DEFAULT NULL )
NESTED TABLE cv STORE AS cvs_table
TABLESPACE users
  STORAGE (INITIAL    32K
        NEXT          32K
        MINEXTENTS    1
        MAXEXTENTS    999
        PCTINCREASE 0);

ALTER TABLE docs ADD CONSTRAINT pk_documents_id PRIMARY KEY (id);
[an error occurred while processing this directive]
[an error occurred while processing this directive](none)
< Вернуться на caйт :: Copyright © 1999 — 2010, IT • archiv.