Большой файл Java для сохранения в базе данных - Проектирование объектов - PullRequest
1 голос
/ 25 августа 2011

Я пытаюсь выяснить объектный дизайн для реализации хранилища больших файлов (~ 600 МБ) в Базе данных с использованием спящего режима. Пожалуйста, предложите правильный подход / дизайн?

class ModelClass{

String name;  //meta data
...

Option 1. 
    byte[] file; // dont want to load the content of the entire file 
                           // in memory by using this but hibernate recognizes 
                           // this datatype
Option 2.
    InputStream inputStream;
    OutputStream outputStream;
    // I can have the methods to provide the input or output stream 
              // but i dont think its a clean approach. I am not sure how 
              // I will be able to work with hibernate with streams
Option 3.
    File fileHandle; 
}

Любые другие варианты ??

Я хотел бы вызвать метод save (Object) hibernateTemplate для сохранения объекта в базе данных. Не знаю, должен ли я иметь только метаданные в классе и обрабатывать файл отдельно и сохранять его.

Заранее спасибо.

Другим работоспособным решением является использование интерфейса «Работа». Целью было избежать загрузки содержимого файла в память.

session.doWork(new Work(){
    @Override
    public void execute(Connection conn) {
        //direct sql queries go here 
    }

});

Ответы [ 3 ]

1 голос
/ 25 августа 2011

Я написал класс SerializableFile, который хранит данные в файле. Когда объект читается, он создает временный файл. Вот оно:

public class SerializableFile implements Serializable {
    private static final File TEMP_DIR = getTempDir();

    private transient boolean temporary;
    private transient String name;
    private transient File file;

    public SerializableFile() {
    }

    public SerializableFile(File file) {
        this.file = file;
        this.name = file.getName();
        this.temporary = false;
    }

    @Override
    protected void finalize() throws Throwable {
        dispose();
        super.finalize();
    }

    public void dispose() {
        if (temporary && file != null) {
            file.delete();
            file = null;
        }
    }

    public File keep(String name) throws IOException {
        if (temporary) {
            temporary = false;
        } else {
            File newFile = new File(TEMP_DIR, name);
            keepAs(newFile);
            file = newFile;
        }
        return file;
    }

    public void keepAs(File outFile) throws IOException {
        if ((temporary || file.equals(outFile)) && file.renameTo(outFile)) {
            temporary = false;
            file = outFile;
        } else {
            InputStream in = new FileInputStream(file);
            try {
                OutputStream out = new FileOutputStream(outFile);
                try {
                    byte buf[] = new byte[4096];
                    for (int n = in.read(buf); n > 0; n = in.read(buf)) {
                        out.write(buf, 0, n);
                    }
                } finally {
                    out.close();
                }
            } finally {
                in.close();
            }
            outFile.setLastModified(file.lastModified());
        }
    }

    public String getName() {
        return name;
    }

    public File getFile() {
        return file;
    }

    public long lastModified() {
        return file.lastModified();
    }

    private void writeObject(ObjectOutputStream out) throws IOException {
        int size = (int)file.length();
        long date = file.lastModified();
        out.writeUTF(name);
        out.writeInt(size);
        out.writeLong(date);
        InputStream in = new FileInputStream(file);
        try {
            byte buf[] = new byte[4096];
            while (size > 0) {
                int n = in.read(buf);
                if (n <= 0 || n > size) {
                    throw new IOException("Unexpected file size");
                }
                out.write(buf, 0, n);
                size -= n;
            }
        } finally {
            in.close();
        }
    }

    private void readObject(ObjectInputStream in) throws IOException {
        name = in.readUTF();
        int size = in.readInt();
        long date = in.readLong();
        file = File.createTempFile("tmp", ".tmp", TEMP_DIR);
        OutputStream out = new FileOutputStream(file);
        try {
            byte buf[] = new byte[4096];
            while (size > 0) {
                int n = in.read(buf, 0, size <= buf.length ? size : buf.length);
                if (n <= 0 || n > size) {
                    throw new IOException("Unexpected file size");
                }
                out.write(buf, 0, n);
                size -= n;
            }
        } finally {
            out.close();
        }
        file.setLastModified(date);
        temporary = true;
    }

    private static File getTempDir() {
        File dir;
        String temp = System.getProperty("com.lagalerie.live.temp-dir");
        if (temp != null) {
            dir = new File(temp);
        } else {
            String home = System.getProperty("user.home");
            dir = new File(home, "temp");
        }
        if (!dir.isDirectory() && !dir.mkdirs()) {
            throw new RuntimeException("Could not create temp dir " + dir);
        }
        return dir;
    }
}
0 голосов
/ 25 августа 2011

Даже если вы все еще используете RDBMS в качестве хранилища данных, вам следует рассмотреть возможность сохранения этих двоичных данных в файловой системе и сохранения каталога / местоположения пути в базе данных, а не сохранять его как BLOB или CLOB в базу данных.

0 голосов
/ 25 августа 2011

Open JPA поддерживает аннотацию @Persistent с некоторыми базами данных :

  • MySQL
  • Oracle
  • PostgreSQL
  • SQL Server
  • DB2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...