2008-10-28 12 views
15

Tengo un POJO específico que necesita persistir en una base de datos, el diseño actual especifica su campo como una columna de cadena única, y agregar campos adicionales a la tabla no es una opción.Serialización casera frente a Java

Es decir, los objetos deben ser serializados de alguna manera. Así que solo para la implementación básica fui y diseñé mi propia forma serializada del objeto, lo que significaba concatenar todos sus campos en una secuencia agradable, separados por un delimitador que elegí. Pero esto es bastante feo y puede causar problemas, por ejemplo, si uno de los campos contiene mi delimitador.

Así que probé la serialización básica de Java, pero a partir de una prueba básica que realicé, esto de alguna manera se convierte en una operación muy costosa (construir un ByteArrayOutputStream, un ObjectOutputStream, etc. para la deserialización).

¿Cuáles son mis opciones? ¿Cuál es la forma preferida para serializar objetos para ir a una base de datos?

Editar: esto va a ser una operación muy común en mi proyecto, por lo que los gastos generales deben mantenerse al mínimo, y el rendimiento es crucial. Además, las soluciones de terceros son buenas, pero irrelevantes (y generalmente generan gastos generales que trato de evitar)

Respuesta

12

Elliot Rusty Harold escribió un nice argument contra el uso de la serialización de objetos Java para los objetos en su biblioteca XOM. Los mismos principios se aplican a ti. La serialización de Java incorporada es específica de Java, frágil y lenta, por lo que es mejor evitarla.

Tiene la idea correcta al usar un formato basado en cadenas. El problema, como dices, es que te estás encontrando con problemas de formato/sintaxis con delimitadores. La solución es usar un formato que ya está diseñado para manejar esto. Si se trata de un formato estandarizado, también puede utilizar otras bibliotecas/idiomas para manipularlo. Además, un formato basado en cadenas significa que tiene la esperanza de comprenderlo simplemente observando los datos; los formatos binarios eliminan esa opción.

XML y JSON son dos excelentes opciones aquí; Están estandarizados, basados ​​en texto, son flexibles, legibles y tienen mucho soporte de biblioteca. También funcionarán sorprendentemente bien (a veces incluso más rápido que la serialización de Java).

+3

He encontrado que XML y JSON son 5 veces más lentos que la serialización de Java. ¿Tiene algún ejemplo de dónde son más rápidos? –

+1

La serialización Java incorporada también es JVM-specfic también.No es portátil de ninguna manera – mcjabberz

+0

No hay nada en ese enlace que constituya un "buen argumento", o incluso un argumento. Solo una serie de comentarios desechables, no todos correctos. – EJP

3

Considere poner los datos en un objeto Properties y use su serialización load()/store(). Esa es una técnica basada en texto lo que es todavía legible en la base de datos:

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 
} 

Para cargar de cuerda, qué similar usando un nuevo objeto y Propertiesload() los datos.

Esto es mejor que la serialización de Java porque es muy legible y compacto.

Si necesita soporte para diferentes tipos de datos (es decir, no solo String), use BeanUtils para convertir cada campo en una representación de cadena.

+0

Jason gracias por su ayuda, las dos últimas soluciones son, lamentablemente, irrelevantes para esto. ¿Puedes elaborar sobre el primero? –

+0

¡Claro! Ver mi respuesta actualizada. –

2

Diría que su enfoque inicial no es del todo malo si su POJO se compone de cadenas y tipos primitivos. Puede forzar el escape del delimitador para evitar corrupciones. Además, si utiliza Hibernate encapsula la serialización en un custom type.

Si no le importa otra dependencia, se supone que Hessian es una forma más eficiente de serializar objetos Java.

3

XStream o YAML o OGNL me vienen a la mente técnicas de serialización fáciles. XML ha sido el más común, pero OGNL ofrece la mayor flexibilidad con la menor cantidad de metadatos.

1

Puede optimizar la serialización externalizando su objeto. Eso le dará control total sobre cómo se serializa y mejorará el rendimiento del proceso. Esto es simple de hacer, siempre que su POJO sea simple (es decir, no tenga referencias a otros objetos), de lo contrario, puede romper fácilmente la serialización.

tutorial here

EDIT: No dando a entender que este es el enfoque preferido, pero está muy limitado en sus opciones si ti es el rendimiento crítico y sólo se puede utilizar una columna de cadena en la tabla.

0

Tengo un POJO determinado que debe conservarse en una base de datos, el diseño actual especifica su campo como una sola columna de cadena, y agregar campos adicionales a la tabla no es una opción.

¿Podría crear una nueva tabla y poner una clave foránea en esa columna!?!? :) ¡Sospecho que no, pero cubramos todas las bases!

serialización: Hemos tenido recientemente esta discusión de manera que si nuestros bloqueos de la aplicación podemos resucitarlo en el mismo estado en que fueron. Básicamente enviamos un evento de persistencia a una cola, y luego esto toma el objeto, lo bloquea y luego lo serializa. Esto parece bastante rápido. ¿Cuántos datos está serializando? ¿Puedes hacer que las variables sean transitorias (es decir, variables en caché)? ¿Puedes considerar dividir tu serialización? Cuidado: ¿qué ocurre si los objetos cambian (bloqueo) o cambian las clases (identificador de serialización diferente)? Tendrá que actualizar todo lo que se serializa a las últimas clases. ¿Quizás solo necesites almacenar esto de la noche a la mañana para que no importe?

XML: Puede usar algo como xstream para lograrlo. Crear algo personalizado es posible (¡una buena pregunta para la entrevista!), Pero probablemente yo no lo haga. ¿Por qué molestarse? Recuerde si tiene enlaces cíclicos o si tiene referencias a objetos más de una vez. Reconstruir los objetos no es tan trivial.

de almacenamiento de base de datos: Si está utilizando Oracle 10g para almacenar manchas, actualice a la última versión, ya que el rendimiento c/burbuja se incrementa de forma masiva. Si estamos hablando de grandes cantidades de datos, ¿tal vez comprimir el flujo de salida?

¿Es esta una aplicación en tiempo real, o habrá una segunda o dos pausas en las que puede persistir con seguridad el objeto real? Si tienes tiempo, entonces puedes clonarlo y luego persistir el clon en otro hilo. ¿Para qué es la persistencia? ¿Es crítico que se haga dentro de una transacción?

0

Considere cambiar su esquema. Incluso si encuentra una manera rápida de serializar un POJO en una cadena, ¿cómo maneja las diferentes versiones? ¿Cómo se migra la base de datos de X-> Y? O peor de A-> D? Estoy viendo problemas donde almacenamos un objeto de serialización en un campo BLOB y tenemos que migrar a un cliente a través de múltiples versiones.

4

Debe tener en cuenta el control de versiones en su solución.La incompatibilidad de datos es un problema que experimentará con cualquier solución que implique el uso de una serialización binaria del objeto. ¿Cómo se carga una fila de datos más antigua en una versión más nueva del objeto?

Por lo tanto, las soluciones anteriores que implican la serialización de un nombre/valor pares es el enfoque que probablemente desee utilizar.

Una solución es incluir un número de versión como uno de los valores de campo. A medida que se agregan, modifican o eliminan nuevos campos, la versión se puede modificar.

Al deserializar los datos, puede tener diferentes controladores de deserialización para cada versión que se pueden usar para convertir datos de una versión a otra.

2

¿Y el mecanismo de persistencia JavaBeans estándar:

java.beans.XMLEncoder 
java.beans.XMLDecoder 

Estos son capaces de crear POJOs Java a partir de XML (que se han persistido a XML). De memoria, se ve (algo) como ...

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

Usted tiene que proporcionar PersistenceDelegate clases para que sepa cómo conservar las clases definidas por el usuario. Suponiendo que no elimina ningún método público, es resistente a los cambios de esquema.

12

Puede probar Protocol Buffers, es un proyecto de fuente abierta de Google, se dice que es rápido (genera una forma serializada más corta que XML, y funciona más rápido). También maneja la adición de un nuevo campo suavemente (inserta valores por defecto).

0

¿Has mirado en JAXB? Es un mecanismo mediante el cual puede definir un conjunto de objetos java que se crean a partir de un esquema XML. Le permite ordenar de una jerarquía de objetos a XML o volver a colocar el XML en una jerarquía de objetos.

0

Voy a una segunda sugerencia para usar JAXB, o posiblemente XStream (el primero es más rápido, el último tiene más enfoque en la parte de serialización de objetos). Además, sugeriré una alternativa decente basada en JSON, Jackson (http://jackson.codehaus.org/Tutorial), que puede serializar/deserializar por completo los beans al texto JSON para almacenar en la columna.

Ah, y estoy absolutamente de acuerdo en que no utilice la serialización binaria Java bajo ninguna circunstancia para el almacenamiento de datos a largo plazo. Lo mismo ocurre con los Buffers de Protocolo; ambos son demasiado frágiles para este propósito (son mejores para la transferencia de datos entre sistemas acoplados).

1

Si está utilizando un delimitador se puede utilizar un carácter que usted sabe que nunca se producen en el texto como \ 0 o símbolos especiales http://unicode.org/charts/symbols.html

Sin embargo, el tiempo dedicado a enviar los datos a la base de datos y persistirlo es probable que sea mucho más grande que el costo de la serialización. Así que sugiero comenzar con algo simple y fácil de leer (como XStream) y ver dónde está gastando la mayor parte de su aplicación y optimizarla.

0

Puede probar Preon. Preon pretende ser con datos binarios codificados lo que Hibernate es para bases de datos relacionales y JAXB para XML.

Cuestiones relacionadas