杰瑞科技汇

Java如何操作Oracle的Blob字段?

Of course! Working with BLOB (Binary Large Object) data in Java with an Oracle database is a common task for handling large binary files like images, videos, documents, etc.

Java如何操作Oracle的Blob字段?-图1
(图片来源网络,侵删)

Here’s a comprehensive guide covering the key concepts, methods, and a complete, runnable example.


What is a BLOB?

A BLOB is a database data type used to store large amounts of binary data. Unlike a CLOB (Character Large Object), which stores character data, a BLOB stores raw binary data (bytes). This makes it ideal for:

  • Images (JPG, PNG, GIF)
  • Videos (MP4, AVI)
  • Audio files (MP3, WAV)
  • Documents (PDF, DOCX, ZIP archives)
  • Any other non-textual file.

Key Java Classes

  • java.sql.Blob: This is the JDBC interface that represents a BLOB value. It provides methods to manage the data, such as getting its length, retrieving a stream to read it, or getting a binary stream to write to it.
  • oracle.sql.BLOB: This is Oracle's specific implementation of the java.sql.Blob interface. When you retrieve a BLOB from an Oracle database, the JDBC driver will typically give you an instance of this class, which has more powerful features than the standard interface.

Core Operations

There are three primary scenarios you'll encounter:

  1. Inserting a BLOB: Writing binary data from a file or an input stream into a new database record.
  2. Reading a BLOB: Retrieving binary data from a database record and saving it to a file or writing it to an output stream.
  3. Updating a BLOB: Modifying the content of an existing BLOB in the database.

Important Prerequisite: Oracle JDBC Driver

You must have the Oracle JDBC driver (JAR file) in your project's classpath. The modern driver is ojdbc8.jar (for Java 8) or ojdbc11.jar (for Java 11+).

Java如何操作Oracle的Blob字段?-图2
(图片来源网络,侵删)

If you're using Maven, add this dependency to your pom.xml:

<dependency>
    <groupId>com.oracle.database.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>21.5.0.0</version> <!-- Use the latest version available -->
</dependency>

Complete Example

Let's walk through a full example that includes:

  1. Creating a table.
  2. Inserting a BLOB.
  3. Reading a BLOB.
  4. Updating a BLOB.

Step 1: Setup Database Table

First, create a table in your Oracle database to store the BLOBs.

CREATE TABLE my_documents (
    id          NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    name        VARCHAR2(255) NOT NULL,
    document_content BLOB,
    created_date TIMESTAMP DEFAULT SYSTIMESTAMP
);

Step 2: Java Code (BlobExample.java)

This class demonstrates all three operations. It uses try-with-resources to ensure that database connections and file streams are always closed properly.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class BlobExample {
    // --- Database Connection Details ---
    // IMPORTANT: Replace with your actual database details
    private static final String DB_URL = "jdbc:oracle:thin:@localhost:1521:ORCLPDB1";
    private static final String DB_USER = "your_username";
    private static final String DB_PASSWORD = "your_password";
    public static void main(String[] args) {
        // The file we will use for the example
        File sourceFile = new File("sample.pdf"); // Make sure this file exists
        File outputFile = new File("output_from_db.pdf");
        // 1. Insert a BLOB into the database
        System.out.println("Inserting BLOB...");
        long insertedId = insertBlob(sourceFile);
        System.out.println("BLOB inserted with ID: " + insertedId);
        // 2. Read the BLOB from the database and save it to a new file
        System.out.println("\nReading BLOB with ID: " + insertedId);
        readBlob(insertedId, outputFile);
        System.out.println("BLOB read and saved to: " + outputFile.getAbsolutePath());
        // 3. Update the BLOB in the database
        File anotherFile = new File("another_document.docx"); // Make sure this file exists
        System.out.println("\nUpdating BLOB with ID: " + insertedId);
        updateBlob(insertedId, anotherFile);
        System.out.println("BLOB updated.");
        // 4. Read the updated BLOB to verify
        System.out.println("\nReading updated BLOB with ID: " + insertedId);
        readBlob(insertedId, new File("updated_output.docx"));
        System.out.println("Updated BLOB read and saved.");
    }
    /**
     * Inserts a BLOB into the database from a file.
     */
    public static long insertBlob(File fileToInsert) {
        final String sql = "INSERT INTO my_documents (name, document_content) VALUES (?, EMPTY_BLOB()) RETURNING id, document_content INTO ?, ?";
        // Using try-with-resources for Connection and PreparedStatement
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, fileToInsert.getName());
            // Register the OUT parameters for the RETURNING clause
            // The first '?' is for the ID (LONG)
            pstmt.registerOutParameter(2, java.sql.Types.NUMERIC);
            // The second '?' is for the BLOB (oracle.sql.BLOB)
            pstmt.registerOutParameter(3, oracle.jdbc.OracleTypes.BLOB);
            // Execute the insert. This does not yet write the BLOB data.
            pstmt.executeUpdate();
            // Now, get the BLOB locator from the OUT parameter
            oracle.sql.BLOB blob = (oracle.sql.BLOB) pstmt.getObject(3);
            long newId = pstmt.getLong(2);
            // Write the file's content to the BLOB locator
            try (InputStream inputStream = new FileInputStream(fileToInsert);
                 OutputStream outputStream = blob.getBinaryOutputStream()) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
            return newId;
        } catch (SQLException | IOException e) {
            e.printStackTrace();
            return -1;
        }
    }
    /**
     * Reads a BLOB from the database and saves it to a file.
     */
    public static void readBlob(long id, File outputFile) {
        final String sql = "SELECT document_content FROM my_documents WHERE id = ?";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            ResultSet rs = pstmt.executeQuery();
            if (rs.next()) {
                // Get the BLOB object from the result set
                java.sql.Blob blob = rs.getBlob("document_content");
                // Get an input stream from the BLOB
                try (InputStream inputStream = blob.getBinaryStream();
                     OutputStream outputStream = new FileOutputStream(outputFile)) {
                    byte[] buffer = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = inputStream.read(buffer)) != -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    }
                }
            } else {
                System.out.println("No record found with ID: " + id);
            }
        } catch (SQLException | IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * Updates an existing BLOB in the database.
     */
    public static void updateBlob(long id, File fileToUpdate) {
        final String sql = "UPDATE my_documents SET document_content = EMPTY_BLOB() WHERE id = ? RETURNING document_content INTO ?";
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setLong(1, id);
            // Register the OUT parameter for the BLOB locator
            pstmt.registerOutParameter(2, oracle.jdbc.OracleTypes.BLOB);
            // Execute the update. This gets a new, empty BLOB locator.
            pstmt.executeUpdate();
            // Get the BLOB locator from the OUT parameter
            oracle.sql.BLOB blob = (oracle.sql.BLOB) pstmt.getObject(2);
            // Write the new file's content to the BLOB locator
            try (InputStream inputStream = new FileInputStream(fileToUpdate);
                 OutputStream outputStream = blob.getBinaryOutputStream()) {
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
            }
        } catch (SQLException | IOException e) {
            e.printStackTrace();
        }
    }
}

Best Practices and Important Considerations

  1. Use try-with-resources: Always wrap your Connection, PreparedStatement, ResultSet, InputStream, and OutputStream objects in try-with-resources blocks. This guarantees they are closed automatically, preventing resource leaks.

  2. Use PreparedStatement with RETURNING Clause (for Oracle): This is the most efficient way to handle BLOBs. Instead of inserting an empty BLOB and then doing a separate UPDATE, you can do it in one step:

    • INSERT ... RETURNING document_content INTO ?
    • This gives you a "locator" to the BLOB in the database immediately after the insert, which you can then write to directly. This avoids the overhead of a second UPDATE statement.
  3. Memory Management: Loading a very large BLOB (e.g., a multi-gigabyte video) directly into memory using blob.getBytes() is a very bad idea and will likely cause an OutOfMemoryError. Always use streams (getBinaryStream() and setBinaryStream()) for large BLOBs. The example above correctly uses streams, which is the recommended approach.

  4. Transactions: BLOB operations can be slow. It's good practice to wrap them in a transaction to ensure data integrity.

    conn.setAutoCommit(false); // Start transaction
    // ... perform your BLOB insert/update operations ...
    conn.commit(); // Commit the transaction
    // or conn.rollback(); if something goes wrong
  5. BLOB vs. CLOB:

    • Use BLOB for any binary data (images, videos, PDFs, etc.).
    • Use CLOB for large text data (XML, JSON, long text articles). Character sets are handled correctly with CLOBs, which is not the case with BLOBs.
分享:
扫描分享到社交APP
上一篇
下一篇