В настоящее время я экспериментирую с хранением больших файлов в базе данных MySQL 5.5 с использованием Java.Мой основной класс называется FileDatabaseTest.Он имеет следующий метод:
import java.sql.*;
import java.io.*;
...
public class FileDatabaseTest {
...
private void uploadToDatabase(File file, String description) {
try {
PreparedStatement stmt = connection.prepareStatement(
"INSERT INTO FILES (FILENAME, FILESIZE, FILEDESCRIPTION, FILEDATA) " +
"VALUES (?, ?, ?, ?)");
stmt.setString(1, file.getName());
stmt.setLong(2, file.length());
stmt.setString(3, description);
stmt.setBinaryStream(4, new FileInputStream(file));
stmt.executeUpdate();
updateFileList();
stmt.close();
} catch(SQLException e) {
e.printStackTrace();
} catch(FileNotFoundException e) {//thrown by FileInputStream constructor
e.printStackTrace();
} catch(SecurityException e) { //thrown by FileInputStream constructor
e.printStackTrace();
}
}
...
}
База данных имеет только одну таблицу - таблицу "FILES" и имеет следующие столбцы.
ID - AUTOINCREMENT, PRIMARY KEY
FILENAME - VARCHAR(100)
FILESIZE - BIGINT
FILEDESCRIPTION - VARCHAR(500)
FILEDATA - LONGBLOB
Программа работает нормально, когдазагрузка небольших документов, но когда я загружаю файлы размером около 20 МБ, процесс загрузки идет очень медленно.Поэтому я попытался поместить FileInputStream в BufferedInputStream в следующем коде:
stmt.setBinaryStream(4, new BufferedInputStream(new FileInputStream(file));
Процесс загрузки стал очень быстрым.Это как копирование файла в другой каталог.Но когда я попытался загрузить файлы размером более 400 МБ, я получил следующую ошибку:
Exception in thread "Thread-5" java.lang.OutOfMemoryError: Java heap space
at com.mysql.jdbc.Buffer.ensureCapacity(Buffer.java:156)
at com.mysql.jdbc.Buffer.writeBytesNoNull(Buffer.java:514)
at com.mysql.jdbc.PreparedStatement.escapeblockFast(PreparedStatement.java:1169)
at com.mysql.jdbc.PreparedStatement.streamToBytes(PreparedStatement.java:5064)
at com.mysql.jdbc.PreparedStatement.fillSendPacket(PreparedStatement.java:2560)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2401)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2345)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2330)
at FileDatabaseTest$2.run(FileDatabaseTest.java:312)
at java.lang.Thread.run(Thread.java:662)
Поэтому я попытался использовать встроенную базу данных Apache-Derby вместо MySQL, и я не получил ошибку.Мне удалось загрузить файлы размером 500 МБ в 1,5 ГБ в базу данных Derby с помощью BufferedInputStream.Я также заметил, что при использовании BufferedInputStream с сервером MySQL при загрузке больших файлов JVM потребляет много памяти, в то время как при использовании его в базе данных Derby использование памяти JVM поддерживается на уровне 85–100 МБ.
Я относительно новичок в MySQL, и я просто использую его настройки по умолчанию.Единственное, что я изменил в его конфигурации, это размер "max_allowed_packet", поэтому я могу загрузить до 2 ГБ файла в базу данных.Поэтому мне интересно, откуда появилась ошибка.Это ошибка MySQL или коннектор MySQL / J?или что-то не так с моим кодом?
То, чего я пытаюсь достичь, - это возможность загружать большие файлы (до 2 ГБ) на сервер MySQL, используя java, без увеличения пространства кучи java.