2010-01-23 14 views
8

Czy można zapisać coś podobnego do poniższego przy użyciu tylko jednej tabeli? W tej chwili, co zrobi hibernacja, to stworzyć dwie tabele, jedną dla rodzin i jedną dla ludzi. Chciałbym, aby obiekt familymembers był serializowany do kolumny w bazie danych.Przechowywanie obiektów w kolumnach za pomocą Hibernate JPA

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

    private final List<Person> familyMembers; 

} 

class Person{ 

    String firstName, lastName; 
    int age; 

} 
+0

To nie jest jasne. Jeśli widzisz rodzinę jako grupę osób, potrzebujesz nowej tabeli dla rodziny, chyba że reprezentujesz rodzinę prostym typem, takim jak liczba całkowita lub ciąg znaków. – Kartoch

+1

OT: To byłby zły projekt. –

+0

Jeśli rodzina ma 3 członków, jakiej wartości spodziewałbyś się w kolumnie bazy danych? –

Odpowiedz

0

Można tworzyć pseudoproperty (getter i setter), który akceptuje/zwraca formularz odcinkach i opisanie familyMembers z @Transient. Będzie to również wymagało dodania adnotacji do pobierających, a nie pól dla wszystkich innych właściwości.

1

Dodaj adnotację do właściwości za pomocą @Column i określ typ, który ma być ArrayList, a nie tylko List. I spraw, aby Person zaimplementował Serializable.

Ale powinieneś to zrobić tylko wtedy, gdy twoje motywy są bardzo jasne, ponieważ jest to poprawne rozwiązanie w bardzo rzadkich przypadkach. Jak zauważył Pascal, jeśli kiedykolwiek będziesz musiał zmienić Person będziesz mieć bóle głowy.

+0

Jestem prawie pewny, że to się nie powiedzie z 'java.lang.ClassCastException: java.util.ArrayList nie można przesłać do java.sql.Blob'A –

+0

tak, przyjrzałem się jednej klasie mojej, gdzie jestem mając tę ​​samą sytuację - działa on z Lotu i tototu, określając konkretny typ (ArrayList).Zaktualizowano odpowiedź: – Bozho

13

To jest okropny projekt i naprawdę nie polecam go (powinieneś po prostu stworzyć inny stół), ale jest to możliwe.

Najpierw należy użyć atrybutu byte[], aby zachować zserializowaną wersję listy osób, które będą przechowywane w obiekcie BLOB w bazie danych. Więc zanotuj, że to jest getter z @Lob (chciałbym sprawić, żeby setter i private nie wystawiały ich). Następnie ujawnij "fałszywy" program pobierający i ustawiający, aby powrócić lub ustawić List<Person> z . Używam z Commons Lang w poniższym przykładzie (pod warunkiem, że nie masz własnej klasy pomocniczej, jeśli nie chcesz importować tej biblioteki) do serializowania/deserializacji w locie do/z byte[]. Nie zapomnij oznaczyć "fałszywego" gettera za pomocą @Transcient lub Hibernate spróbuje utworzyć pole (i nie powiedzie się, ponieważ nie będzie w stanie określić typu dla 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); 
    } 
} 

Nie zapomnij zrobić klasę SerializablePerson i dodać prawdziwy serialVersionUID (ja po prostu pokazano domyślne tutaj):

public class Person implements Serializable { 

    private static final long serialVersionUID = 1L; 

    // ... 

    private String firstName, lastName; 
    private int age; 

} 

Ale pozwól mi nalegać, to jest straszny projekt i będzie bardzo delikatny (zmiana Person może wymagać "migracji" zawartości obiektu BLOB, aby uniknąć problemów z deserializacją, co stanie się bolesne. Powinieneś naprawdę rozważyć ten pomysł i zamiast tego użyć innej tabeli dla Person (lub Nie rozumiem, dlaczego korzystasz z bazy danych)

+0

dlaczego nie możesz użyć bazy danych, być może dlatego, że używanie jej jest bezcelowe? Jeśli wszystko, czego potrzebuję, to przechowywać listę czegoś, nie muszę umieszczać jej w osobnej bazie danych. – Enerccio

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

jeśli nie można używać hibernacji adnotacje spróbuj tego:

@Lob 
private Serializable familyMembers; 

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

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

Tak, ale to nie jest adnotacja JPA. –

+0

patrz aktualizacja odpowiedzi –

Powiązane problemy