Чтение и запись LOB объектов

Вопросам использования больших объектов LOB (Large Object Bynary) зачастую приходится уделять пристальное внимание. Связано это с хранением различных файлов в таблицах базы данных (БД). Сразу же возникает вопрос, зачем хранить в БД файл, если потом придется извлекать его назад опять же в виде в файла? Ведь можно создать отдельное файловое хранилище. Ответ также оказывается простым и тривиальным - для файлового хранилища требуется дополнительно решать вопросы репликации и синхронизации, предоставление прав доступа и создание backup'a. Таким образом, если нельзя обойтись без LOB-объектов, то остается выбрать их тип - бинарный (BLOB Binary Large Object ) или символьный, называемый в БД различных провайдеров по-разному (CLOB, TEXT).

ПРИМЕЧАНИЕ : при работе с символьными данными необходимо учитывать кодировку. Это вопрос будет учтен при записи текстового файла в таблицы БД и выгрузки из БД.

Описание примера

В статье рассматривается пример записи и чтения нескольких типов файлов в поля BLOB и CLOB (TEXT). В качестве серверов БД были использованы Oracle 10g Enterprise Edition, Oracle 10g Express Edition и MySQL 5.1.

Пример представляет собой проект Eclipse, реализующий все принципы ООП (объектно-ориентированное программирование) - наследование, инкапсуляция и полиморфизм. Структура проекта представлена на следующем скриншоте.

В директории «lib» размещаются библиотеки JDBC для подключения к серверам БД. При подключении к серверу 10g Enterprise Edition использовалась библиотека ojdbc7.jar. В случае использования сервера 10g Express Edition были использованы библиотеки ojdbc14_g.jar, ojdbc14.jar. Для подключения в IDE Eclipse библиотеки к проекту необходимо ее выделить и в контекстном меню выбрать "Build Path/Add to Build Path". Чтобы отключить использование библиотеки в проекте используйте вкладку "Java Build Path" в окне свойств проекта.

Пример включает следующие программные модули :

DAOBase.java базовый модуль создания подключения к серверу БД и работы с полями BLOB и CLOB (TEXT);
MainTest.java главный модуль тестирования методов чтения и записи LOB;
MySQLDAO.java модуль создания подключения к серверу MySQL, наследует DAOBase.java;
OracleDAO.java модуль создания подключения к серверу Oracle, наследует DAOBase.java;
Файлы для тестирования aircraft.jpg, отчет.xlsx, текст.txt

Приложение в двух разнотипных БД создает таблицы с полями BLOB и CLOB (TEXT), в которые сначала файлы записываются, потом выполняется их чтение. Представленные процедуры записи и чтения больших объектов Вы можете использовать в своих приложениях практически без доработок.

Создание подключений Connection к различным серверам БД описано здесь и в данной статье не рассматривает (код представлен). Пример можно скачать здесь.

Описание базового модуля, DAOBase.java

Базовый модуль включает следующие основные методы :

МетодНазначениеПримечание
public void createConnection() Создание Connection, подключение к БД Переопределяется для каждого провайдера БД
public Connection getConnection() Получение Connection
public void closeConnection() Закрытие Connection
public boolean execSQL (sql) Выполнение SQL-запроса
public boolean writeBlob(table, field, pk, id, fpath) Запись файла в поле BLOB таблицы
public long readBlobToFile(table, field, pk, id, fpath) Извлечение объекта BLOB в файл
public boolean writeClob(table, field, id, fpath) Запись файла в поле CLOB таблицы
public long readClobToFile(table, field, id, path) Извлечение объекта CLOB в файл
public String readClobData(table, field, id) Чтение объекта CLOB

Параметры процедур записи и чтения больших объектов LOB включают наименование таблиц table, наименование LOB-полей field, наименование поля первичного ключа pk, идентификатор записи id и путь к файлу fpath. При необходимости Вы можете доработать данные процедуры и включить в качестве параметра наименование схемы Schema(Oracle) или базы данных Database (MySQL). Не исключено, что и первичный ключ может содержать несколько полей.

ПРИМЕЧАНИЕ :
1. Следует обратить внимание, что методы работы с полями BLOB и CLOB не переопределяются согласно представленной выше таблице. Но это касается баз данных Oracle и MySQL, используемые в примере. Т.е. можно сказать, что методы JDBC «справляются» с полями LOB данных провайдеров. К тому же в MySQL используется тип TEXT, а в Oracle CLOB.
2. Можно использовать различные методы записи в поля LOB содержимое файлов, что будет продемонстрировано на примере MySQL.

Ниже представлен листинг DAOBase.java, где методы работы с полями BLOB и CLOB не включают код. Это сделано преднамеренно для наглядного представления общей структуры модуля DAOBase.java. В противном случае листинг сильно увеличится и «за деревьями нельзя будет увидеть лес». Код методов работы с полями LOB описан далее.

Листинг DAOBase.java

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class DAOBase 
{
    protected Connection connection = null;

    protected final int  BUFFER_length = 2 * 1024;
    private final String TABLE_DROP    = "DROP TABLE %s";
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public void createConnection(){}
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public Connection getConnection()
    {
        return connection;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public void closeConnection() {
        if(connection != null){
            try {
                connection.close();
            } catch(SQLException e){
                System.out.println(e.getMessage());
            }
        }
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /**
     * Функция выполнения SQL-запроса
     * @param sql текст запроса
     * @return результат выполнения запроса
     */
    public boolean execSQL (final String sql) {
        boolean result = false;
        try {
            Statement statement = null
            if (connection != null) {
                statement = connection.createStatement();
                statement.execute(sql);
                statement.close();
                statement = null;
                result = true;
            }
        } catch (SQLException e) {
            System.err.println ("SQLException : code = " + 
                                String.valueOf(e.getErrorCode()) 
                                     + " - " + e.getMessage());
            System.err.println ("\tSQL : " + sql);
            
        }
        return result;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public boolean writeBlob(final String table,
                             final String field, 
                             final String pk,
                             final int id, 
                             final String fpath)
    {
        boolean result = false;
        // ... см. код ниже
        return result;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public long readBlobToFile(final String table,
                               final String field, 
                               final String pk,
                               final int id, final String path) 
                              throws IOException, SQLException
    {
        long size = 0;
        // ... см. код ниже
        return size;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public boolean writeClob(final int id, final String fpath)
    {
       boolean result = false;
        // ... см. код ниже
        return result;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public long readClobToFile(final String table, 
                               final String field, 
                               final int id,
                               final String path) 
           throws IOException, SQLException
    {
        long size = 0;
        // ... см. код ниже
        return size;
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public String readClobData(final String table, 
                               final String field,
                               final int id)
    {
        StringBuffer buffer = new StringBuffer();
        // ... см. код ниже
        return buffer.toString();
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public boolean createTable(final String sql)
    {
        return execSQL (sql);
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    public boolean dropTable(final String table)
    {
        return execSQL (String.format(TABLE_DROP, table));
    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}

Процедуры создания createTable (sql) и удаления dropTable(sql) таблицы БД не включены в общий список методов DAOBase.java, поскольку в примере выполняют вспомогательную функцию и используется для «подыгрыша». Как правило, структура БД меняется редко и нет необходимости включать в приложение процедуры, которые не используются.

Листинг методов чтения и записи данных в поле BLOB

Две вспомогательные функции readBlobField и writeFromBlob2Stream имеют модификаторы private и используются основным методом readBlobToFile при выгрузке файла из БД.

Для записи файла в поле BLOB используется метод setBinaryStream, получающий в качестве параметра поток FileInputStream. При выгрузке файла из БД в методе readBlobToFile сначала читается объект BLOB (readBlobField), после этого он записывается в выходной поток OutputStream в методе writeFromBlob2Stream, где используется метод чтения в бинарный поток getBinaryStream() объекта BLOB.

private String INSERT_blob = "insert into %s(%s) values(%d)"    ;
private String UPDATE_blob = "update %s set %s = ? where %s = ?";
private String SELECT_blob = "select %s from %s where %s = %d"  ;	
	
public boolean writeBlob(final String table, 
                         final String field, 
                         final String pk, 
                         final int id, 
                         final String fpath)
{
    String sql = String.format(INSERT_blob, table, pk, id);
    boolean result = execSQL (sql);
    if (result) {
        PreparedStatement ps = null;
        File file = new File(fpath);
        try {
            sql = String.format(UPDATE_blob, table, field, pk);
            FileInputStream is = new FileInputStream(file);
            ps = connection.prepareStatement(sql);
            ps.setBinaryStream(1, is, (int)file.length());
            ps.setInt(2, id);
            ps.executeUpdate();

            connection.commit();
            ps.close();
        } catch (FileNotFoundException e) {
            result = false;
            e.printStackTrace();
        } catch (SQLException e) {
            result = false;
            e.printStackTrace();
        }
    }
    return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private Blob readBlobField(final String table,
                           final String field, 
                           final String pk,
                           final int id) throws SQLException 
{
    String sql = String.format(SELECT_blob, field, table, pk, id);
    Statement stmt = connection.createStatement();
    ResultSet rs = stmt.executeQuery(sql); 
    Blob blob = null; 
    if (rs.next()) 
        blob = rs.getBlob(1); 
    return blob; 
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private long writeFromBlob2Stream(Blob blob, OutputStream out)
                                     throws SQLException, IOException
{ 
    InputStream is = blob.getBinaryStream(); 
    int length = -1; 
    long size = 0;
    byte[] buf = new byte[BUFFER_length]; 
    while ((length = is.read(buf)) != -1) { 
        out.write(buf, 0, length); 
        size += length; 
    } 
    is.close(); 
    return size; 
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public long readBlobToFile(final String table,
                           final String field, 
                           final String pk,
                           final int id,
                           final String fpath) 
                                 throws IOException, SQLException
{ 
    long size = 0; 
    OutputStream fwriter = new FileOutputStream(fpath);
    Blob blob =  readBlobField(table, field, pk, id);
    size = writeFromBlob2Stream(blob, fwriter); 
    fwriter.close(); 
    return size; 
}

Листинг процедур чтения и записи данных в поле CLOB

Две вспомогательные функции readClobField и readFromClob2Stream имеют модификаторы private и используются основными методами readClobToFile, readClobData при выгрузке файла из БД.

Чтобы учесть кодировку символов при записи текстового файла в БД используется InputStreamReader и BufferedReader. Для записи файла в поле CLOB/TEXT используется метод setCharacterStream объекта CLOB, которому передается BufferedReader. При выгрузке файла из БД в методе readClobToFile сначала читается объект CLOB (readClobField ), после этого он записывается в выходной поток BufferedWriter в методе readFromClob2Stream, где используется метод чтения в символьный поток getCharacterStream() объекта CLOB.

protected String INSERT_clob = "insert into %s(%s) values(%d)"    ;
protected String UPDATE_clob = "update %s set %s = ? where %s = ?";
private   String SELECT_clob = "select %s from %s where id = %d"  ;

public boolean writeClob(final String table,
                         final String field, 
                         final String pk,
                         final int id,
                         final String fpath)
{
    String sql = String.format(INSERT_clob, table, pk, id);
    boolean result = execSQL (sql);
    if (result) {
        PreparedStatement ps = null;
        File file = new File(fpath);

        try {
            FileInputStream   fis=new FileInputStream  (file);
            InputStreamReader isr=new InputStreamReader(fis,"UTF-8");
            BufferedReader    br =new BufferedReader   (isr);

            sql = String.format(UPDATE_clob, table, field, pk);
            ps = connection.prepareStatement(sql);
            ps.setCharacterStream(1, br, (int)file.length());
            ps.setInt(2, id);
            ps.executeUpdate();

            connection.commit();
            ps.close();
        } catch (UnsupportedEncodingException e) {
            result = false;
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            result = false;
            e.printStackTrace();
        } catch (SQLException e) {
            result = false;
            e.printStackTrace();
        }
    }
    return result;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public long readClobToFile(final String table,
                           final String field, 
                           final int id, 
                           final String fpath) 
                                throws IOException, SQLException
{
    long size = 0; 
    BufferedWriter fwriter=new BufferedWriter(new FileWriter(fpath));
    Clob clob = readClobField (table, field, id);
    size = readFromClob2Stream(clob, fwriter); 
    fwriter.close(); 
    return size; 
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private Clob readClobField(final String table,
                           final String field,
                           final int id) throws SQLException
{ 
    String sql = String.format(SELECT_clob, field, table, id);
    Statement stmt = connection.createStatement(); 
    ResultSet rs = stmt.executeQuery(sql); 
    Clob clob = null; 
    if (rs.next()) 
        clob = rs.getClob(1); 
    return clob; 
} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private long readFromClob2Stream(Clob clob, Writer out) 
                                   throws SQLException, IOException
{ 
    BufferedReader breader;
    breader; = new BufferedReader(clob.getCharacterStream());
    int length = -1; 
    long size = 0; 
    char[] buf = new char[BUFFER_length]; 
    while ((length = breader.read(buf, 0, BUFFER_length)) != -1) {
        out.write(buf, 0, length); 
        size += length; 
    } 
    breader.close(); 
    return size; 
} 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public String readClobData(final String table,
                           final String field,
                           final int id)
{
    StringBuffer buffer = new StringBuffer();
    try {
        Clob clob = readClobField (table, field, id);
        BufferedReader reader;
        reader = new BufferedReader(clob.getCharacterStream());
        char[] buf = new char[BUFFER_length];
        int length = -1; 
        try {
            while ((length=reader.read(buf,0,BUFFER_length)) != -1){
                if (length == BUFFER_length)
                    buffer.append(String.valueOf(buf));
                else {
                    String tmp = String.valueOf(buf)
                                       .substring(0, length);
                    buffer.append(tmp);
                }
            }
            reader.close(); 
        } catch (IOException e) {
            e.printStackTrace();
        } 
    } catch (SQLException e) {
        e.printStackTrace();
    }
    return buffer.toString();
}	

Листинг OracleDAO.java

Листинг модуля OracleDAO.java включает переопределенные метод createConnection() и метод создания процедур БД createTable. Структуры таблиц, описанные в константах TABLE_blobs и TABLE_files в виде SQL-скриптов, включают только поля идентификаторов id и поля data соответствующих типов LOB. По умолчанию поля дата имеют значения NULL, поскольку используются в методах при обновлении.

При создании объекта в конструкторе сразу же создается подключение к серверу БД. В качестве свойства объекту подключения передается кодировка устанавливаемого соединения "utf8".

private final String DRIVER_oracle = "oracle.jdbc.OracleDriver";
private final String URL_oracle    = "jdbc:oracle:thin:@%s:%d:%s";

private final String URL_host      = "localhost";
private final int    PORT_oracle   = 1521;
		
private final String SCHEMA_oracle = "...";
private final String login         = "...";
private final String password      = "...";


private final String TABLE_blobs   = "CREATE TABLE blobs( "        +
                                          "id   INT PRIMARY KEY, " +
                                          "data BLOB NULL)" ;
private final String TABLE_files   = "CREATE TABLE files( "        +
                                          "id   INT PRIMARY KEY, " +
                                          "data CLOB NULL)" ;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public OracleDAO()
{
    createConnection();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void createConnection()
{
    try {
        // Регистрация драйвера
        Class.forName(DRIVER_oracle).newInstance();
        // Определение свойств подключения Connection
        Properties properties = new Properties();
        properties.setProperty("password"         , password);
        properties.setProperty("user"             , login   );
        properties.setProperty("useUnicode"       , "true"  );
        properties.setProperty("characterEncoding", "utf8"  );
			
        String url = String.format(URL_oracle, URL_host, 
                                   PORT_oracle, SCHEMA_oracle);
        connection_ora = (OracleConnection) 
                        DriverManager.getConnection(url, properties);
        connection_ora.setAutoCommit(false);
    } catch (InstantiationException e) {
    } catch (IllegalAccessException e) {
    } catch (ClassNotFoundException e) {
    } catch (SQLException           e) {
        connection_ora = null;
    }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean createTable(final String table)
{
    if (table.equalsIgnoreCase("blobs"))
        return execSQL (TABLE_blobs);
    else if (table.equalsIgnoreCase("files"))
        return execSQL (TABLE_files);
    else
        return false;
}

Листинг MySQLDAO.java

Листинг модуля MySQLDAO.java включает переопределенные метод createConnection(), метод создания процедур БД createTable и метод writeClob, который демонстрирует другой подход записи символьного файла в поле TEXT. В данном методе файловый поток FileInputStream сразу же перенаправляется в поток setAsciiStream. Но чтобы не исказить символы использовалась соответствующая кодировка в таблице БД и подключении к серверу. Родительский метод writeClob класса DAOBase.java также сработал без нареканий. Таким образом, в Вашем распоряжении 2 подхода записи текстового файла в БД MySQL.

Структуры таблиц, описанные в константах TABLE_blobs и TABLE_files в виде SQL-скриптов, включают только поля идентификаторов id и поля data соответствующих типов LOB. Для таблицы "files" установлена кодировка "UTF8". По умолчанию поля дата имеют значения NULL, т.к. используются в методах при обновлении.

При создании объекта в конструкторе сразу же создается подключение к серверу БД, которому в качестве свойства передается кодировка устанавливаемого соединения "utf8".

private String  DRIVER_MySQL = "com.mysql.jdbc.Driver";
private String  URL_mysql    = "jdbc:mysql://%s:%d/%s";

private String  URL_host     = "localhost"            ;
private int     PORT_mysql   = 3306                   ;
private String  DATABASE     = "test"                 ;

private String  login        = "..."                  ;
private String  password     = "..."                  ;

private String  TABLE_blobs  = "CREATE TABLE blobs( "        +
                                   "id    INT PRIMARY KEY, " +
                                   "data  BLOB NULL)";
private String  TABLE_files  = "CREATE TABLE files( "        +
                                   "id    INT PRIMARY KEY, " +
                                   "data  TEXT NULL) "       +
                                   "ENGINE = INNODB "        +
                                   "CHARACTER SET utf8 "     +
                                   "COLLATE utf8_general_ci;";
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public MySQLDAO()
{
    createConnection();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public void createConnection()
{
    try {
        // Регистрация драйвера
        Class.forName(DRIVER_MySQL).newInstance();
        // Определение свойств подключения Connection
        Properties properties = new Properties();
        properties.setProperty("password"         , password);
        properties.setProperty("user"             , login   );
        properties.setProperty("useUnicode"       , "true"  );
        properties.setProperty("characterEncoding", "utf8"  );

        String url = String.format(URL_mysql, URL_host, 
                                   PORT_mysql, DATABASE);
        connection = DriverManager.getConnection(url, properties);
        connection.setAutoCommit(false);
    } catch (InstantiationException e) {
    } catch (IllegalAccessException e) {
    } catch (ClassNotFoundException e) {
    } catch (SQLException           e) {
        connection = null;
    }
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean createTable(final String table)
{
    if (table.equalsIgnoreCase("blobs"))
        return execSQL (TABLE_blobs);
    else if (table.equalsIgnoreCase("files"))
        return execSQL (TABLE_files);
    else
        return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean writeClob(final String table, 
                         final String field, 
                         final String pk,
                         final int id,
                         final String fpath)
{
    String sql = String.format(INSERT_clob_rec, table, pk, id);
    boolean result = execSQL (sql);
    if (result) {
        PreparedStatement ps = null;
        File file = new File(fpath);

        try {
            FileInputStream  fis = new FileInputStream  (file);
            sql = String.format(UPDATE_clob_rec, table, field, pk);
            ps = connection.prepareStatement(sql);
            ps.setAsciiStream (1, fis, (int) file.length());
            ps.setInt         (2, id);
            ps.executeUpdate();

            connection.commit();
            ps.close();
        } catch (FileNotFoundException e) {
            result = false;
            e.printStackTrace();
        } catch (SQLException e) {
            result = false;
            e.printStackTrace();
        }
    }
    return result;
}

Тестирование примера

Главный модуль приложения MainTest.java выполняет тестирование методов записи файлов в БД и выгрузки в файл. Основной метод тестирования testDAO в качестве параметра принимает базовый класс (полиморфизм). В методе testDAO сначала проверяется установка подключения к серверу БД. Если подключение установлено, то создаются таблицы, в которые записываются и извлекаются файлы.

private boolean TEST_mysql  = false;
private boolean TEST_oracle = true;
	
private final String TEXT_tbl_create = "\nTable <%s> created";
private final String TEXT_tbl_insert = "%s inserted into table";
private final String TEXT_tbl_upload = "%s (size %d byte) uploaded";
private final String TEXT_tbl_drop   = "Table <%s> dropped";

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public MainTest()
{
    if (TEST_oracle)
        testOracle();
    if (TEST_mysql)
        testMySQL();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
private void testDAO(DAOBase dao, final String caption)
{
    String text;
    if (dao.getConnection() != null) {
        System.out.println(caption);
        System.out.println("Connection to server");

        if (dao.createTable("blobs")) {
            text = String.format(TEXT_tbl_create, "blobs");
            System.out.println(text);

            if (dao.writeBlob("blobs", "data", "id", 
                                          1, "aircraft.jpg")) {
                text = String.format(TEXT_tbl_insert, "Image");
                System.out.println(text);
                try {
                    long size = dao.readBlobToFile("blobs", "data",
                                          "id", 1, "aircraft1.jpg");
                    text = String.format(TEXT_tbl_upload,
                                          "Image", size);
                    System.out.println(text);
                } catch (IOException e) {
                } catch (SQLException e) {}
            }
            if (dao.writeBlob("blobs", "data", "id",
                                               2, "отчет.xlsx")) {
                text = String.format(TEXT_tbl_insert, "XLSX");
                System.out.println(text);
                try {
                    long size = dao.readBlobToFile("blobs", "data",
                                          "id", 2, "отчет1.xlsx");
                    text = String.format(TEXT_tbl_upload,
                                           "XLSX", size);
                    System.out.println(text);
                } catch (IOException e) {
                } catch (SQLException e) {}
            }

            if (dao.dropTable("blobs")) {
                text = String.format(TEXT_tbl_drop, "blobs");
                System.out.println(text);
            }
        }			
        if (dao.createTable("files")) {
            text = String.format(TEXT_tbl_create, "files");
            System.out.println(text);
            if (dao.writeClob("files", "data", "id", 
                                               1, "текст.txt")) {
                text = String.format(TEXT_tbl_insert, "File");
                System.out.println(text);
                try {
                    // Запись значения поля CLOB в файл
                    long size = dao.readClobToFile("files", "data",
                                                  1, "текст1.txt");
                    text = String.format(TEXT_tbl_upload, 
                                                  "File", size);
                    System.out.println(text);
                } catch (IOException e) {
                } catch (SQLException e) {}
            }
            if (dao.dropTable("files")) {
                text = String.format(TEXT_tbl_drop, "files");
                System.out.println(text);
            }
        }			
        dao.closeConnection();
    } else
        System.out.println("Connection is NULL");
}
private void testMySQL()
{
    DAOBase dao = new MySQLDAO();
    testDAO(dao, "----- TEST MySQL -----\n");
}
private void testOracle()
{
    DAOBase dao = new OracleDAO();
    testDAO(dao, "----- TEST Oracle -----\n");
}
public static void main(String[] args)
{
    new MainTest();
    System.exit(0);
}

Результаты тестирования

Приложение выводит сообщения и результатах тестирования методов записи и чтения LOB-объектов в консоль.


----- TEST Oracle -----

Connection to server

Table <blobs> created
Image inserted into table
Image (size 3573 byte) uploaded
XLSX inserted into table
XLSX (size 9929 byte) uploaded
Table <blobs> dropped

Table <files> created
File inserted into table
File (size 2191 byte) uploaded
Table <files> dropped
 

Скачать пример

Исходный код рассмотренного примера записи и чтения больших объектов LOB с использованием JDBC можно скачать здесь (7.27 Мб).

При тестировании примера необходимо определить параметры подключения к Вашему серверу БД - схема (база данных), логин и пароль.

  Рейтинг@Mail.ru