410013796724260
• Webmoney
R335386147728
Z369087728698
Чтение и запись 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" в окне свойств проекта. Пример включает следующие программные модули :
Приложение в двух разнотипных БД создает таблицы с полями BLOB и CLOB (TEXT), в которые сначала файлы записываются, потом выполняется их чтение. Представленные процедуры записи и чтения больших объектов Вы можете использовать в своих приложениях практически без доработок. Создание подключений Connection к различным серверам БД описано здесь и в данной статье не рассматривает (код представлен). Пример можно скачать здесь. Описание базового модуля, DAOBase.javaБазовый модуль включает следующие основные методы :
Параметры процедур записи и чтения больших объектов LOB включают наименование таблиц table, наименование LOB-полей field, наименование поля первичного ключа pk, идентификатор записи id и путь к файлу fpath. При необходимости Вы можете доработать данные процедуры и включить в качестве параметра наименование схемы Schema(Oracle) или базы данных Database (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 Мб). При тестировании примера необходимо определить параметры подключения к Вашему серверу БД - схема (база данных), логин и пароль. |
