2010-01-23 27 views
8

¿Es posible almacenar algo como lo siguiente utilizando solo una tabla? En este momento, lo que hará hibernate es crear dos tablas, una para Familias y otra para personas. Me gustaría que el objeto de los miembros de la familia se serialice en la columna de la base de datos.Almacenar objetos en columnas con Hibernate JPA

@Entity(name = "family") 
class Family{ 

    private final List<Person> familyMembers; 

} 

class Person{ 

    String firstName, lastName; 
    int age; 

} 
+0

Esto no es clara. Si está viendo familly como un grupo de personas, entonces necesita una nueva tabla para familly, excepto si representa a la familia con un tipo simple como un entero o una cadena. – Kartoch

+1

OT: Eso sería un mal diseño. –

+0

Si una familia tiene 3 miembros, ¿qué valor esperaría ver en la columna de la base de datos? –

Respuesta

0

Puede crear pseudoproperty (get y set) que acepta/devuelve la forma serializada, y anotar el familyMembers con @Transient. Esto también necesitaría anotar los captadores, no los campos, para todas las demás propiedades.

1

Anotar la propiedad con @Column y definir el tipo de ser ArrayList, no sólo List. Y haga Person implemente Serializable.

Pero debe hacerlo solo si sus motivos son muy claros, porque esta es la solución correcta en algunos casos muy raros. Como señaló Pascal, si alguna vez tiene que cambiar Person, tendrá dolores de cabeza.

+0

Estoy bastante seguro de que esto no funcionaría con 'java.lang.ClassCastException: java.util.ArrayList no se puede convertir a java.sql.Blob' –

+0

sí, eché un vistazo a una clase mía donde estoy teniendo la misma situación - funciona con otot Lob, y con la especificación del tipo concreto (ArrayList).Se actualizó la respuesta – Bozho

13

Este es un diseño horrible y realmente no lo estoy recomendando (solo debes crear otra tabla) pero es posible.

En primer lugar, deberá usar un atributo byte[] para contener una versión serializada de la lista de personas que se almacenarán en un BLOB en la base de datos. Así que anote su getter con @Lob (Haría que getter y setter private no los expongan). Luego, exponga getter y setter "falso" para devolver o establecer un List<Person> del byte[]. Estoy usando SerializationUtils de Commons Lang en el ejemplo siguiente (proporcione su propia clase de ayuda si no desea importar esta biblioteca) para serializar/deserializar sobre la marcha a/desde el byte[]. No olvide marcar el captador "falso" con @Transcient o Hibernate intentará crear un campo (y fallar porque no podrá determinar el tipo para un List).

@Entity(name = "family") 
class Family implements Serializable { 

    // ... 

    private byte[] familyMembersAsByteArray; 

    public Family() {} 

    @Lob 
    @Column(name = "members", length = Integer.MAX_VALUE - 1) 
    private byte[] getFamilyMembersAsByteArray() { // not exposed 
     return familyMembersAsByteArray; 
    } 

    private void setFamilyMembersAsByteArray((byte[] familyMembersAsByteArray() { // not exposed 
     this.familyMembersAsByteArray = familyMembersAsByteArray; 
    } 

    @Transient 
    public List<Person> getFamilyMembers() { 
     return (List<Person>) SerializationUtils.deserialize(familyMembersAsByteArray); 
    } 

    public void setParticipants(List familyMembers) { 
     this.familyMembersAsByteArray = SerializationUtils.serialize((Serializable) familyMembers); 
    } 
} 

No se olvide de hacer que la clase SerializablePerson y añadir un verdadero serialVersionUID (sólo estoy mostrando un defecto aquí):

public class Person implements Serializable { 

    private static final long serialVersionUID = 1L; 

    // ... 

    private String firstName, lastName; 
    private int age; 

} 

Pero, permítanme insistir, esta es una horrible diseño y será muy frágil (cambiar Person podría requerir para "migrar" el contenido del BLOB para evitar problemas de deserialización y esto será doloroso. Realmente debería reconsiderar esta idea y usar otra tabla para el Person en su lugar (o yo don no entiendo por qué usa una base de datos).

+0

¿por qué no se puede usar la persona de la base de datos, tal vez porque usarla no tiene sentido? Si todo lo que necesito es almacenar una lista de algo, no necesito ponerlo en una base de datos separada. – Enerccio

1
@Type(type = "serializable") 
private List<Person> familyMembers; 

si no puede utilizar las anotaciones de hibernación a probar esto:

@Lob 
private Serializable familyMembers; 

public List<Person> getFamilyMembers(){ 
    return (List) familyMembers; 
} 

public void setFamilyMembers(List<Person> family){ 
    familyMembers = family; 
} 
+1

Sí, pero esta no es una anotación JPA. –

+0

ver la actualización de la respuesta –