Настройка производительности операции проекта Hibernate+Spring+MySQL, которая хранит изображения, загруженные пользователем

Я работаю над веб-проектом, который является базирующимся Spring+Hibernate+MySQL. Я застреваю в точке, где я должен сохранить изображения, загруженные пользователем в базу данных. Хотя я написал некоторый код, который работает хорошо на данный момент, но я полагаю, что вещи испортят, когда проект пошел бы живой.

Вот мой доменный класс, который несет байты изображения:

@Entity
public class Picture implements java.io.Serializable{
    long id;
    byte[] data;
    ... // getters and setters
}

И вот мой контроллер, который сохранил файл на, отправьте:

public class PictureUploadFormController extends AbstractBaseFormController{
    ...
    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception{
         MutlipartFile file; 
         // getting MultipartFile from the command object
         ...
         // beginning hibernate transaction
         ...
         Picture p=new Picture();
         p.setData(file.getBytes());
         pictureDAO.makePersistent(p); // this method simply calls getSession().saveOrUpdate(p)

         // committing hiernate transaction
         ...
    }
    ...
}

Очевидно, плохая часть кода. Есть ли так или иначе, я мог использовать InputStream или Блоб для сохранения данных вместо первой загрузки всех байтов от пользователя в память и затем продвижение их в базу данных?

Я провел некоторое исследование на поддержке hibernate Блоба и нашел, что это в В спящем режиме В книге Действия:

java.sql. Блоб и java.sql. Clob являются самым эффективным способом обработать большие объекты в Java. К сожалению, экземпляр Blob или Clob только применим, пока транзакция JDBC не завершается. Таким образом, если Ваш персистентный класс определяет свойство java.sql. Clob или java.sql. Блоб (не хорошая идея так или иначе), Вы будете ограничены в том, как могут использоваться экземпляры класса. В частности, Вы не сможете использовать экземпляры того класса как отделенные объекты. Кроме того, много драйверов JDBC не показывают рабочую поддержку java.sql. Блоб и java.sql. Clob. Поэтому имеет больше смысла отображать большие объекты с помощью двоичного файла или текста, отображающего тип, предполагая, что извлечение всего большого объекта в память не является уничтожителем производительности.

Обратите внимание, что можно найти актуальные шаблоны разработки и подсказки для использования большого объекта на Быть в спящем режиме веб-сайте с приемами для конкретных платформ.

Теперь, по-видимому, Блоб не может использоваться, поскольку это не хорошая идея так или иначе, что еще могло использоваться для улучшения производительности? Я не мог найти, что любой актуальный шаблон разработки или любая полезная информация о В спящем режиме веб-сайт. Таким образом, любая справка/рекомендации от stackoverflowers будет очень цениться.

Спасибо

1
задан craftsman 2 May 2010 в 12:03
поделиться

1 ответ

В пересмотренном издании книги (Java Persistence with Hibernate) говорится:

В таблице 5.3 перечислены типы Hibernate для работы с двоичными данными и большими значениями. Обратите внимание, что только binary поддерживается в качестве типа свойства идентификатора.

Mapping type   Java type   Standard SQL built-in type
binary         byte[]               VARBINARY
text           java.lang.String     CLOB
clob           java.sql.Clob        CLOB
blob           java.sql.Blob        BLOB
serializable   Any Java class that  VARBINARY
               implements
               java.io.Serializable

Если свойство в вашем постоянном классе Java имеет тип byte[], Hibernate может сопоставить его с binary[]. его в столбец VARBINARY с бинарным типом отображения. (Обратите внимание, что реальный тип SQL зависит от диалекта; например, в PostgreSQL тип SQL - BYTEA, а в Oracle - RAW.) Если свойство в вашем постоянном классе Java имеет тип java.lang.String, Hibernate может сопоставить его со столбцом SQL CLOB с типом text тип отображения.

Обратите внимание, что в обоих случаях Hibernate сразу инициализирует значение свойства, когда загружается экземпляр сущности, содержащий переменную свойства. Это неудобно когда приходится иметь дело с потенциально большими значениями.

Одним из решений является ленивая загрузка через перехват доступа к полю по требованию. Однако этот подход требует инструментализации байткода ваших постоянных классов для внедрения дополнительного кода. Мы обсудим ленивую загрузку с помощью инструментария байткода инструментацию и перехват в главе 13, раздел 13.1.6, "Ленивая загрузка с перехватом."

Второе решение - это другой тип свойства в вашем классе Java. JDBC поддерживает объекты-локаторы (LOB) напрямую.1 Если ваше Java-свойство имеет тип java.sql.Clob или java.sql.Blob, вы можете сопоставить его с типом clob или blob mapping чтобы получить ленивую загрузку больших значений без инструментации байткода. Когда владелец свойства загружается, значение свойства является объектом-локатором - фактически, указатель на реальное значение, которое еще не материализовано. Как только вы обращаетесь к свойству, значение материализуется. Эта загрузка по требованию работает только до тех пор, пока транзакция базы данных открыта, поэтому доступ к любому свойству такого типа необходимо получать когда владелец экземпляра сущности находится в постоянном и транзакционном состоянии, а не в отсоединенном состоянии. Ваша доменная модель теперь также привязана к JDBC, потому что требуется импорт пакета java.sql. Хотя классы доменной модели исполняемыми в изолированных модульных тестах, вы не можете получить доступ к свойствам LOB без подключения к базе данных. соединение.

Надеюсь, это поможет.

2
ответ дан 3 September 2019 в 00:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: