简体   繁体   English

JDBC 4的java.sql.Clob.free()方法和向后兼容性

[英]JDBC 4's java.sql.Clob.free() method and backwards compatibility

I'm investigating an interesting performance issue, where there are no calls to java.sql.Clob.free() on a frequently used resource. 我正在调查一个有趣的性能问题,在经常使用的资源上没有调用java.sql.Clob.free() This method on Clob was introduced in Java 6 / JDBC 4, so it might well be that this is actually a regression introduced when upgrading from JDBC 3 to JDBC 4. Clob上的这个方法是在Java 6 / JDBC 4中引入的,所以很可能这实际上是从JDBC 3升级到JDBC 4时引入的回归。

Is this a known issue in the Oracle JDBC driver? 这是Oracle JDBC驱动程序中的已知问题吗? Can it be said that before, Clobs somehow magically freed themselves, whereas with JDBC 4, they MUST be freed manually? 可以说,之前, Clobs以某种方式神奇地释放了自己,而使用JDBC 4,它们必须手动释放? Or is there a driver setting that can be used to stay compatible with JDBC 3? 或者是否有可用于与JDBC 3保持兼容的驱动程序设置?

Note, the same applies to Blob , of course. 注意,当然,这同样适用于Blob

Our application had to be sure to call java.sql.Clob.free() explicitly on oracle.sql.CLOB (used toJdbc() to get java.sql.Clob) with Oracle 11g and 'ojdbc6.jar' (Specification-Version '4.0' and Implementation-Version '11.2.0.3.0' in MANIFEST.MF). 我们的应用程序必须确保在oracle.sql.CLOB(使用toJdbc()获取java.sql.Clob)上使用Oracle 11g和'ojdbc6.jar'显式调用java.sql.Clob.free()(规范 - 版本) MANIFEST.MF中的'4.0'和实现 - 版本'11 .2.0.3.0'。 Otherwise the application suffered from substantial memory leaks. 否则应用程序遭受大量内存泄漏。

I looked up the Oracle vendor JDBC drivers (ojdbc6.jar) for Oracle Database here 在这里查找了Oracle Database的Oracle供应商JDBC驱动程序(ojdbc6.jar)
I found the demo.zip file here 我在这里找到了demo.zip文件
I unzipped it and grepped the source for clob and blob. 我解压缩它,并为clob和blob寻找源代码。
There's a file TemporaryLobJDBC40.java 有一个文件TemporaryLobJDBC40.java
In there, there's a sample where a temp clob and blob are created, then filled with some data, then inserted into a table via a prepared statement (parameterized INSERT). 在那里,有一个示例,其中创建了temp clob和blob,然后填充了一些数据,然后通过预准备语句(参数化INSERT)插入到表中。
Then, the statement is executed, closed, the temp clob and blob are freed and the transaction is committed. 然后,执行,关闭语句,释放temp clob和blob并提交事务。

Then, the author loops through the rows of the table creating permanent blob/clobs and assigning them the objects returned from getClob(), getBlob() and dumps the contents to a stream. 然后,作者循环遍历表的行,创建永久blob / clobs,并为它们分配从getClob(),getBlob()返回的对象,并将内容转储到流中。

The permanent blobs are never freed. 永久性的斑点永远不会被释放。 I assume that after every iteration, as the objects go out of scope, the garbage collector frees these objects automatically. 我假设在每次迭代后,当对象超出范围时,垃圾收集器会自动释放这些对象。

After the last iteration, the last two Blob / Clob objects are not explicitly freed, but get implicitly cleaned up by the garbage collector (when it decides to start) their scope ended with the last iteration. 在最后一次迭代之后,最后两个Blob / Clob对象没有被显式释放,但是被垃圾回收器(当它决定启动时)隐式清理它们的范围以最后一次迭代结束。 (after the }) (之后 })

Personally, I'd do the cleanup explicitly, but to each his own. 就个人而言,我会明确地进行清理工作,但要对每个人进行清理。 This demo shows that you can 这个演示表明你可以
do it either way. 无论如何都要这样做。

Here's the code (TemporaryLobJDBC40.java): 这是代码(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();
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM