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

Я работаю над веб-проектом, основанным на 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 или Blob для сохранения данных, вместо того, чтобы сначала загружать все байты пользователя в память и затем помещать их в базу данных?

Я провел некоторое исследование поддержки hibernate для Blob и нашел это в книге Hibernate In Action:

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

Обратите внимание на вас можно найти современные шаблоны дизайна и советы по использованию крупных объектов на Сайт Hibernate, с хитростями для отдельные платформы.

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

Спасибо

1 Ответ

2 голосов
/ 02 мая 2010

Пересмотренное издание книги ( Java Persistence с 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 может отобразить это столбец VARBINARY с двоичным типом отображения. (Обратите внимание, что реальный тип SQL зависит от диалекта; например, в PostgreSQL типом SQL является BYTEA, а в Oracle это RAW.) Если свойство в вашем постоянном классе Java имеет тип java.lang.String, Hibernate может сопоставить его столбцу SQL CLOB с текстом тип отображения.

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

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

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

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

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