Метод java.sql.Clob.free () и обратная совместимость в JDBC 4 - PullRequest
3 голосов
/ 13 марта 2012

Я исследую интересную проблему с производительностью, когда на часто используемом ресурсе нет вызовов java.sql.Clob.free().Этот метод в Clob был введен в Java 6 / JDBC 4, поэтому вполне возможно, что это регрессия, введенная при обновлении с JDBC 3 до JDBC 4.

Является ли это известной проблемой в OracleДрайвер JDBC?Можно ли сказать, что раньше Clobs каким-то волшебным образом освобождали себя, тогда как в JDBC 4 они ДОЛЖНЫ освобождаться вручную?Или есть параметр драйвера, который можно использовать для обеспечения совместимости с JDBC 3?

Обратите внимание, то же самое относится и к Blob, конечно.

Ответы [ 2 ]

5 голосов
/ 06 июня 2013

Наше приложение должно было обязательно вызывать java.sql.Clob.free () явно для oracle.sql.CLOB (используется toJdbc () для получения java.sql.Clob) с Oracle 11g и 'ojdbc6.jar' (Версия спецификации '4.0' и версия реализации '11 .2.0.3.0 'в MANIFEST.MF).В противном случае приложение столкнулось с существенными утечками памяти.

1 голос
/ 13 марта 2012

Я посмотрел драйверы JDBC поставщика Oracle (ojdbc6.jar) для базы данных Oracle здесь
Я нашел файл demo.zip здесь
Я расстегнул молнию и нашел источник сгустка и капли.
Там есть файл TemporaryLobJDBC40.java
Там есть пример, где создаются временный сгусток и большой двоичный объект, затем заполняются некоторыми данными, а затем вставляются в таблицу с помощью подготовленного оператора (параметризованный INSERT).
Затем оператор исполняется, закрывается, временный клоб и блоб освобождаются, и транзакция фиксируется.

Затем автор перебирает строки таблицы, создавая постоянные blob / clob и присваивая им объекты, возвращенные из getClob (), getBlob (), и выгружает содержимое в поток.

Постоянные капли никогда не освобождаются. Я предполагаю, что после каждой итерации, когда объекты выходят из области видимости, сборщик мусора автоматически освобождает эти объекты.

После последней итерации последние два объекта Blob / Clob не освобождаются явным образом, но неявно очищаются сборщиком мусора (когда он решает начать), их область действия заканчивается с последней итерацией. (после})

Лично я бы сделал уборку явно, но каждому свое. Эта демонстрация показывает, что вы можете
сделай это в любом случае.

Вот код (TemporaryLobJDBC40.java):

/*
 * This sample shows how to create
 * a temporary BLOB and CLOB, write
 * some data to them and then insert
 * them into a table. This makes a 
 * permanent copy in the table. The 
 * temp lobs are still available for
 * further use if desired until the
 * transaction is committed.
 * When fetched from the table, the
 * lobs are no longer temporary.
 *
 * This version uses the new 
 * JDBC 4.0 factory methods in 
 * java.sql.Connection and the
 * free methods in java.sql.Blob and Clob
 *
 * Testing for temporary status still 
 * requires Oracle specfiic APIs in 
 * oracle.sql.BLOB and oracle.sql.CLOB.
 *
 * It needs jdk6 or later version and ojdbc6.jar
 */

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Blob;
import java.sql.Clob;


class TemporaryLobJDBC40
{
  public static void main (String args [])
    throws Exception
  {
    Connection conn = DemoConnectionFactory.getHRConnection( args );
    LobExample.createSchemaObjects( conn );
    Blob tempBlob = conn.createBlob();
    Clob tempClob = conn.createClob();

    System.out.println ("tempBlob.isTemporary()="+
                        ((oracle.sql.BLOB)tempBlob).isTemporary());
    System.out.println ("tempClob.isTemporary()="+
                        ((oracle.sql.CLOB)tempClob).isTemporary());
    LobExample.fill(tempBlob, 100L);
    LobExample.fill(tempClob, 100L);

    String insertSql = "insert into jdbc_demo_lob_table values ( ?, ?, ? )";
    PreparedStatement pstmt = conn.prepareStatement( insertSql );
    pstmt.setString( 1, "one" );
    pstmt.setBlob( 2, tempBlob );
    pstmt.setClob( 3, tempClob );
    pstmt.execute();
    pstmt.close();
    tempBlob.free();
    tempClob.free();
    conn.commit();

    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery( "select b, c from jdbc_demo_lob_table" );
    while( rs.next() )
    {
      Blob permanentBlob = rs.getBlob(1);
      Clob permanentClob = rs.getClob(2);
      System.out.println ("permanentBlob.isTemporary()="+
                          ((oracle.sql.BLOB)permanentBlob).isTemporary());
      System.out.println ("permanentClob.isTemporary()="+
                          ((oracle.sql.CLOB)permanentClob).isTemporary());
      LobExample.dump(permanentBlob);
      LobExample.dump(permanentClob);
    }
    rs.close();
    stmt.close();
    conn.close();
  }
}
...