Java Reference
In-Depth Information
database management systems have been optimized to handle rows containing relatively small
numbers of these types of data fields.
Many modern applications require the management of much larger data objects, from images, which
may require tens of kilobytes of storage, to video clips, which may run into the hundreds of megabytes.
The earliest approach to handling large objects was to store them as files in the underlying operating
system, using the database to store only the file path and letting the application code manage the file.
Today, many enterprise RDBMS systems support large objects directly as special data types, albeit with
certain restrictions on using them in queries.
Since large objects are, by definition, large, they are managed using SQL locators. Conceptually, a
locator is similar to a C or C++ pointer which contains the location of an object rather than the object
itself. RDBMS systems use locators to manage large objects because handling them
in-line
destroys
the optimization that RDBMS systems perform to map data objects to physical-storage devices such as
disk sectors.
An important feature of
ARRAYs
,
BLOBs
, and
CLOBs
, is that, since they are accessed using locators,
you can manipulate them without having to copy all the data from the server to the client machine. In
fact, when you query a database for a large object, the locator, rather than the actual object, is returned
in the ResultSet. Using pointers in this way is more efficient than moving large quantities of data around
the system for each column, so this feature can improve performance dramatically. As a JDBC
developer, you won't have to deal with locators, but it is useful to understand the concept so you can
see why the various large-object manipulation methods work the way they do.
Once you have the locator, you must specifically ask for the large-object data. This process is known as
materializing
the data. For example, to retrieve an image stored as a
BLOB
, you can materialize it either
as a byte array, using
Blob.getBytes()
, or as an
InputStream
, using
Blob.getBinaryStream()
.
Although this chapter focuses on the use of Blobs and Clobs, you can see from
Table 14-1
that large-
object support works consistently for all of these data types. Once you understand how to handle one,
you understand them all.
Using Blobs to Store Binary Data
Blobs provide a means of storing and managing large quantities of binary data. Typical examples of
large binary data objects are audio and video clips and image files. Blobs are particularly useful in Web
applications for storing images. JDBC support for Blobs is provided by the
Blob Interface
, which
defines these access methods:
public InputStream getBinaryStream()
public byte[] getBytes(long position, int length)
In addition, the
Blob
interface defines the utility methods
length()
and
position()
, which return
the number of bytes in the
Blob
and the offset to a contained byte array or
Blob
. The
ResultSet
method
getBlob()
is used to retrieve the locator of a
Blob
from a
ResultSet
, while the method
setBlob()
in the
PreparedStatement
interface can be used to set a
Blob.
In practice, a more
common way to write a Blob to a database table is to use
PreparedStatement.setBinaryStream()
to transfer data directly from an
InputStream
to the RDBMS system. An example of this approach is
shown in
Listing 14-1
.
Listing 14-1: Inserting a Blob into a table
package JavaDatabaseBible.ch14;
import java.io.*;
import java.sql.*;
import javax.sql.*;