Сериализация самодельных и Java - PullRequest
15 голосов
/ 28 октября 2008

У меня есть определенный POJO, который необходимо сохранить в базе данных, текущий дизайн определяет его поле как однострочный столбец, и добавление дополнительных полей в таблицу не вариант.

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

Итак, я попробовал базовую сериализацию Java, но из проведенного мною основного теста это почему-то становится очень дорогой операцией (создание ByteArrayOutputStream, ObjectOutputStream и т. Д., То же самое для десериализации).

Так, каковы мои варианты? Каков предпочтительный способ сериализации объектов в базе данных?

Редактировать: это будет очень распространенная операция в моем проекте, поэтому накладные расходы должны быть сведены к минимуму, а производительность имеет решающее значение. Кроме того, сторонние решения хороши, но не имеют значения (и обычно приводят к накладным расходам, которых я стараюсь избегать)

Ответы [ 14 ]

12 голосов
/ 29 октября 2008

Вы можете попробовать Protocol Buffers , это проект с открытым исходным кодом от Google, говорят, что он быстрый (генерирует более короткую сериализованную форму, чем XML, и работает быстрее). Он также аккуратно обрабатывает добавление нового поля (вставляет значения по умолчанию).

12 голосов
/ 28 октября 2008

Эллиот Расти Гарольд написал хороший аргумент против использования сериализации Java Object для объектов в его библиотеке XOM. Те же принципы применяются к вам. Встроенная Java-сериализация является специфичной для Java, хрупкой и медленной, поэтому ее лучше избегать.

Вы имеете примерно правильное представление об использовании формата на основе строк. Проблема, как вы заявляете, заключается в том, что вы сталкиваетесь с проблемами форматирования / синтаксиса с разделителями. Решение состоит в том, чтобы использовать формат, который уже создан, чтобы справиться с этим. Если это стандартизированный формат, то вы также можете использовать другие библиотеки / языки для управления им. Кроме того, строковый формат означает, что у вас есть надежда понять его, просто взглянув на данные; двоичные форматы снимают эту опцию.

XML и JSON - два отличных варианта; они стандартизированы, основаны на тексте, гибки, удобочитаемы и имеют большую поддержку библиотек. Они также будут работать на удивление хорошо (иногда даже на 1007 * быстрее , чем сериализация Java).

4 голосов
/ 29 октября 2008

Вам необходимо учесть версию в вашем решении. Несовместимость данных - это проблема, с которой вы столкнетесь при любом решении, которое включает использование двоичной сериализации Объекта. Как загрузить более старую строку данных в более новую версию объекта?

Итак, вышеприведенные решения, которые включают сериализацию в пары имя / значение, - это подход, который вы, вероятно, захотите использовать.

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

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

3 голосов
/ 28 октября 2008

XStream или YAML или OGNL приходят на ум как простые методы сериализации. XML был наиболее распространенным, но OGNL обеспечивает наибольшую гибкость при минимальном количестве метаданных.

3 голосов
/ 28 октября 2008

Рассмотрите возможность помещения данных в объект Properties и используйте его сериализацию load()/store(). Это текстовая техника, поэтому она по-прежнему читается в базе данных:

public String getFieldsAsString() {
  Properties data = new Properties();
  data.setProperty( "foo", this.getFoo() );
  data.setProperty( "bar", this.getBar() );
  ...
  ByteArrayOutputStream out = new ByteArrayOutputStream();
  data.store( out, "" );
  return new String( out.toByteArray(), "8859-1" );   //store() always uses this encoding
}

Для загрузки из строки выполните аналогичные действия, используя новый объект Properties и load() данные.

Это лучше, чем Java-сериализация, потому что она очень удобочитаема и компактна.

Если вам требуется поддержка различных типов данных (т.е. не только String), используйте BeanUtils для преобразования каждого поля в строковое представление и из него.

2 голосов
/ 29 октября 2008

Как насчет стандартного механизма персистентности JavaBeans:

java.beans.XMLEncoder
java.beans.XMLDecoder

Они могут создавать Java POJO из XML (которые были сохранены в XML). По памяти это выглядит (что-то) как ...

<object class="java.util.HashMap">
    <void method="put">
        <string>Hello</string>
        <float>1</float>
    </void>
</object>

Вы должны предоставить PersistenceDelegate классы, чтобы он знал, как сохранить пользовательские классы. Предполагая, что вы не удаляете открытые методы, он устойчив к изменениям схемы.

2 голосов
/ 28 октября 2008

Я бы сказал, что ваш первоначальный подход не так уж и плох, если ваш POJO состоит из строк и примитивных типов. Вы можете принудительно экранировать разделитель, чтобы предотвратить искажения. Также, если вы используете Hibernate, вы инкапсулируете сериализацию в пользовательский тип .

Если вы не возражаете против другой зависимости, Hessian предположительно является более эффективным способом сериализации объектов Java.

1 голос
/ 14 марта 2009

Если вы используете разделитель, вы можете использовать символ, который, как вы знаете, никогда не встречается в вашем тексте, например \ 0, или специальные символы http://unicode.org/charts/symbols.html

Однако время, затрачиваемое на отправку данных в базу данных и ее сохранение, вероятно, будет намного больше, чем стоимость сериализации. Поэтому я бы предложил начать с чего-то простого и удобного для чтения (например, XStream), посмотреть, где ваше приложение проводит большую часть своего времени, и оптимизировать его.

1 голос
/ 28 октября 2008

Вы можете оптимизировать сериализацию, выполняя внешний вид вашего объекта. Это даст вам полный контроль над сериализацией и улучшит производительность процесса. Это просто сделать, если ваш POJO прост (т.е. не имеет ссылок на другие объекты), в противном случае вы можете легко прервать сериализацию.

учебник здесь

РЕДАКТИРОВАТЬ: не подразумевает, что это предпочтительный подход, но вы очень ограничены в своих параметрах, если ti критичен к производительности, и вы можете использовать только строковый столбец в таблице.

0 голосов
/ 12 августа 2009

Вы можете попробовать Преон . Preon стремится к двоичным закодированным данным, как Hibernate для реляционных баз данных и JAXB к XML.

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