Семинар по самообслуживанию и Java

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

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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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

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

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

Ответ 4

Рассмотрите возможность размещения данных в объекте 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 для преобразования каждого поля в и из строковое представление.

Ответ 5

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

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

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

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

Ответ 9

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

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

Ответ 10

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

Не могли бы вы создать новую таблицу и поместить внешний ключ в этот столбец!?!?:) Я подозреваю, что нет, но пусть покрывает все базы!

Сериализация: Мы недавно провели это обсуждение, чтобы, если наше приложение аварийно, мы можем воскресить его в том же состоянии, что и ранее. Мы по существу отправляем событие стойкости в очередь, а затем захватываем объект, блокируем его и затем сериализуем. Это кажется довольно быстрым. Сколько данных вы сериализуете? Можете ли вы сделать какие-либо переменные переходными (т.е. Кэшированные переменные)? Можете ли вы рассмотреть возможность разделения вашей сериализации? Остерегайтесь: что произойдет, если ваши объекты изменяются (блокировка) или классы меняются (различный идентификатор сериализации)? Вам нужно будет обновить все, что сериализуется до последних классов. Возможно, вам нужно только хранить эту ночь, чтобы это не имело значения?

XML: Вы можете использовать что-то вроде xstream для достижения этого. Построение чего-то обыденного выполнимо (хороший вопрос для интервью!), Но я бы, наверное, не сделал этого сам. Зачем беспокоиться? Помните, если у вас есть циклические ссылки или у вас есть ссылки на объекты более одного раза. Восстановление объектов не совсем так тривиально.

Хранилище базы данных: Если вы используете Oracle 10g для хранения блобов, обновляйтесь до последней версии, так как производительность c/blob значительно увеличивается. Если мы говорим о больших объемах данных, то, возможно, запишите выходной поток?

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

Ответ 11

Рассмотрите возможность изменения вашей схемы. Даже если вы найдете быстрый способ сериализации POJO для строки, как вы обрабатываете разные версии? Как вы переносите базу данных из X- > Y? Или хуже от A- > D? Я вижу проблемы, когда мы сохраняем объект сериализации в поле BLOB и должны переносить клиента на несколько версий.

Ответ 12

Вы просмотрели JAXB? Это механизм, с помощью которого вы можете определить набор Java-объектов, созданных из XML-схемы. Он позволяет вам маршировать из иерархии объектов в XML или отменять XML обратно в иерархию объектов.

Ответ 13

Я предпочел бы использовать JAXB, или, возможно, XStream (прежний быстр, последний больше ориентирован на часть сериализации объекта). Кроме того, я буду предлагать достойную альтернативу JSON, Джексон (http://jackson.codehaus.org/Tutorial), которая может полностью сериализовать/десериализовать beans к тексту JSON для хранения в столбце.

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

Ответ 14

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