# 使用大对象

> 原文： [https://docs.oracle.com/javase/tutorial/jdbc/basics/blob.html](https://docs.oracle.com/javase/tutorial/jdbc/basics/blob.html)

`Blob`，`Clob`和`NClob` Java 对象的一个​​重要特性是，您可以操作它们，而无需将所有数据从数据库服务器带到客户端计算机。某些实现表示这些类型的实例，其中包含实例所代表的数据库中对象的定位符（逻辑指针）。由于`BLOB`，`CLOB`或`NCLOB` SQL 对象可能非常大，因此使用定位器可以显着提高性能。但是，其他实现完全实现了客户端计算机上的大对象。

如果要将`BLOB`，`CLOB`或`NCLOB` SQL 值的数据带到客户端计算机，请使用为`Blob`，`Clob`和`NClob` Java 接口提供的方法。这个目的。这些大对象类型对象实现了它们表示为流的对象的数据。

涵盖以下主题：

*   [将大对象类型对象添加到数据库](#add_lob)
*   [检索 CLOB 值](#retrieve_clob)
*   [添加和检索 BLOB 对象](#add_retrieve_blob)
*   [释放大型物体持有的资源](#release_large_objects)

以下摘自 `[ClobSample.addRowToCoffeeDescriptions](gettingstarted.html)`将`CLOB` SQL 值添加到表`COFFEE_DESCRIPTIONS`。 `Clob` Java 对象`myClob`包含`fileName`指定的文件的内容。

```
public void addRowToCoffeeDescriptions(
    String coffeeName, String fileName)
    throws SQLException {

    PreparedStatement pstmt = null;
    try {
        Clob myClob = this.con.createClob();
        Writer clobWriter = myClob.setCharacterStream(1);
        String str = this.readFile(fileName, clobWriter);
        System.out.println("Wrote the following: " +
            clobWriter.toString());

        if (this.settings.dbms.equals("mysql")) {
            System.out.println(
                "MySQL, setting String in Clob " +
                "object with setString method");
            myClob.setString(1, str);
        }
        System.out.println("Length of Clob: " + myClob.length());

        String sql = "INSERT INTO COFFEE_DESCRIPTIONS " +
                     "VALUES(?,?)";

        pstmt = this.con.prepareStatement(sql);
        pstmt.setString(1, coffeeName);
        pstmt.setClob(2, myClob);
        pstmt.executeUpdate();
    } catch (SQLException sqlex) {
        JDBCTutorialUtilities.printSQLException(sqlex);
    } catch (Exception ex) {
      System.out.println("Unexpected exception: " + ex.toString());
    } finally {
        if (pstmt != null)pstmt.close();
    }
}

```

以下行创建`Clob` Java 对象：

```
Clob myClob = this.con.createClob();

```

以下行检索一个流（在本例中为`Writer`对象，名为`clobWriter`），用于将字符流写入`Clob` Java 对象`myClob`。方法`ClobSample.readFile`写入这个字符流;流来自`String` `fileName`指定的文件。方法参数`1`表示`Writer`对象将开始在`Clob`值的开头写入字符流：

```
Writer clobWriter = myClob.setCharacterStream(1);

```

`ClobSample.readFile`方法逐行读取文件`fileName`指定的文件，并将其写入`writerArg`指定的`Writer`对象：

```
private String readFile(String fileName, Writer writerArg)
        throws FileNotFoundException, IOException {

    BufferedReader br = new BufferedReader(new FileReader(fileName));
    String nextLine = "";
    StringBuffer sb = new StringBuffer();
    while ((nextLine = br.readLine()) != null) {
        System.out.println("Writing: " + nextLine);
        writerArg.write(nextLine);
        sb.append(nextLine);
    }
    // Convert the content into to a string
    String clobData = sb.toString();

    // Return the data.
    return clobData;
}

```

以下摘录创建`PreparedStatement`对象`pstmt`，将`Clob` Java 对象`myClob`插入`COFFEE_DESCRIPTIONS`：

```
PreparedStatement pstmt = null;
// ...
String sql = "INSERT INTO COFFEE_DESCRIPTIONS VALUES(?,?)";
pstmt = this.con.prepareStatement(sql);
pstmt.setString(1, coffeeName);
pstmt.setClob(2, myClob);
pstmt.executeUpdate();

```

方法 `[ClobSample.retrieveExcerpt](gettingstarted.html)`从列值`COF_NAME`等于`String`的行中检索存储在`COFFEE_DESCRIPTIONS`的`COF_DESC`列中的`CLOB` SQL 值] `coffeeName`参数指定的值：

```
public String retrieveExcerpt(String coffeeName, int numChar)
    throws SQLException {

    String description = null;
    Clob myClob = null;
    PreparedStatement pstmt = null;

    try {
        String sql =
            "select COF_DESC " +
            "from COFFEE_DESCRIPTIONS " +
            "where COF_NAME = ?";

        pstmt = this.con.prepareStatement(sql);
        pstmt.setString(1, coffeeName);
        ResultSet rs = pstmt.executeQuery();

        if (rs.next()) {
            myClob = rs.getClob(1);
            System.out.println("Length of retrieved Clob: " +
                myClob.length());
        }
        description = myClob.getSubString(1, numChar);
    } catch (SQLException sqlex) {
        JDBCTutorialUtilities.printSQLException(sqlex);
    } catch (Exception ex) {
        System.out.println("Unexpected exception: " + ex.toString());
    } finally {
        if (pstmt != null) pstmt.close();
    }
    return description;
}

```

以下行从`ResultSet`对象`rs`中检索`Clob` Java 值：

```
myClob = rs.getClob(1);

```

以下行从`myClob`对象中检索子字符串。子串从`myClob`的第一个字符开始，最多包含`numChar`中指定的连续字符数，其中`numChar`是整数。

```
description = myClob.getSubString(1, numChar);

```

添加和检索`BLOB` SQL 对象与添加和检索`CLOB` SQL 对象类似。使用`Blob.setBinaryStream`方法检索`OutputStream`对象以写入`Blob` Java 对象（称为方法）所代表的`BLOB` SQL 值。

`Blob`，`Clob`和`NClob` Java 对象至少在创建它们的事务期间保持有效。这可能导致应用程序在长时间运行的事务期间耗尽资源。应用程序可以通过调用`free`方法释放`Blob`，`Clob`和`NClob`资源。

在下面的摘录中，调用方法`Clob.free`以释放为先前创建的`Clob`对象保留的资源：

```
Clob aClob = con.createClob();
int numWritten = aClob.setString(1, val);
aClob.free();

```