2010-01-23 2 views
8

È possibile memorizzare qualcosa come il seguente usando solo una tabella? In questo momento, ciò che l'ibernazione farà è creare due tavoli, uno per le famiglie e uno per le persone. Vorrei che l'oggetto familymembers fosse serializzato nella colonna del database.Memorizzazione di oggetti in colonne utilizzando Hibernate JPA

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

    private final List<Person> familyMembers; 

} 

class Person{ 

    String firstName, lastName; 
    int age; 

} 
+0

Questo non è chiaro. Se stai vedendo familly come un gruppo di persone, allora hai bisogno di un nuovo tavolo per familly, tranne se rappresenti la famiglia con un tipo semplice come un numero intero o una stringa. – Kartoch

+1

OT: Sarebbe un cattivo progetto. –

+0

Se una famiglia ha 3 membri, quale valore ti aspetti di vedere nella colonna del database? –

risposta

0

È possibile creare pseudoproperty (getter e setter) che accetta/restituisce il modulo serializzato, e annotare il familyMembers con @Transient. Ciò dovrebbe anche annotare i getter, non i campi, per tutte le altre proprietà.

1

Annotare la proprietà con @Column e definire il tipo da ArrayList, non solo List. E fare Person attuare Serializable.

Ma dovresti farlo solo se i tuoi motivi sono molto chiari, perché questa è la soluzione corretta in alcuni casi molto rari. Come ha notato Pascal, se mai dovessi cambiare Person avrai mal di testa.

+0

Sono abbastanza sicuro che questo fallirebbe con un 'java.lang.ClassCastException: java.util.ArrayList non può essere lanciato su java.sql.Blob' –

+0

sì, ho dato un'occhiata a una mia classe dove sono avendo la stessa situazione - funziona senza Lob e con specificando il tipo concreto (ArrayList).Aggiornamento della risposta – Bozho

13

Questo è un design orribile e in realtà non lo raccomando (dovresti semplicemente creare un altro tavolo) ma è possibile.

Innanzitutto, è necessario utilizzare un attributo byte[] per contenere una versione serializzata dell'elenco di persone che verranno archiviate in un BLOB nel database. Quindi annota che è getter con @Lob (vorrei rendere il getter e setter private per non esporli). Quindi, esporre getter e setter "falsi" per restituire o impostare uno List<Person> dallo byte[]. Sto usando SerializationUtils da Commons Lang nell'esempio qui sotto (fornisci la tua classe di supporto se non vuoi importare questa libreria) per serializzare/deserializzare al volo a/da byte[]. Non dimenticare di contrassegnare il getter "falso" con @Transcient o Hibernate proverà a creare un campo (e fallirà perché non sarà in grado di determinare il tipo per 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); 
    } 
} 

Non dimenticate di fare il Person classe Serializable e di aggiungere un vero e proprio serialVersionUID (sto solo mostrando un default qui):

public class Person implements Serializable { 

    private static final long serialVersionUID = 1L; 

    // ... 

    private String firstName, lastName; 
    private int age; 

} 

Ma, mi permetta di insistere, si tratta di un design orribile e sarà molto fragile (il cambiamento di Person potrebbe richiedere di "migrare" il contenuto del BLOB per evitare problemi di deserializzazione e questo diventerà doloroso. Dovresti davvero riconsiderare questa idea e usare un'altra tabella per lo Person invece (o I don capisco perché usi un database)

+0

perché non si può usare la persona del database, forse perché l'uso è inutile? Se tutto ciò di cui ho bisogno è memorizzare un elenco di qualcosa, non ho bisogno di metterlo in un database separato. – Enerccio

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

se non è possibile utilizzare le annotazioni Hibernate provare questo:

@Lob 
private Serializable familyMembers; 

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

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

Sì, ma Questa non è un'annotazione JPA. –

+0

vedi aggiornamento alla risposta –