2010-01-23 2 views
8

Можно ли хранить что-то вроде следующего, используя только одну таблицу? Прямо сейчас, что спящий режим будет делать, это создать две таблицы, одну для Семьи и одну для людей. Я хотел бы, чтобы объект familymembers был сериализован в столбце базы данных.Сохранение объектов в столбцах с использованием Hibernate JPA

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

    private final List<Person> familyMembers; 

} 

class Person{ 

    String firstName, lastName; 
    int age; 

} 
+0

Это не ясно. Если вы видите familly как группу людей, вам нужна новая таблица для familly, за исключением случаев, когда вы представляете familly с простым типом, например, целым числом или строкой. – Kartoch

+1

OT: Это будет плохой дизайн. –

+0

Если у семьи 3 члена, какое значение вы ожидаете увидеть в столбце базы данных? –

ответ

0

Вы можете создать pseudoproperty (геттер и сеттер), который принимает/возвращает последовательную форму, и аннотировать familyMembers с @Transient. Это также необходимо будет аннотировать геттеры, а не поля, для всех других свойств.

1

Аннотация имущества: @Column и укажите тип, который будет ArrayList, а не только List. И сделать Person реализовать Serializable.

Но вы должны сделать это, только если ваши мотивы очень ясны, потому что это правильное решение в некоторых очень редких случаях. Как отметил Паскаль, если вам когда-либо придется менять Person, у вас будут головные боли.

+0

Я уверен, что это не сработает с java.lang.ClassCastException: java.util.ArrayList не может быть передан в java.sql.Blob' –

+0

да, я взглянул на один класс, где я с той же ситуацией - он работает withotu Lob и с указанием конкретного типа (ArrayList).Обновлен ответ – Bozho

13

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

Во-первых, вам нужно будет использовать атрибут byte[] для хранения сериализованной версии списка лиц, которые будут храниться в BLOB в базе данных. Так что аннотируйте его getter с @Lob (я бы сделал геттер и сеттер private, чтобы не выставлять их). Затем выведите «фальшивый» геттер и сеттер для возврата или установите List<Person> с byte[]. Я использую SerializationUtils из Commons Lang в приведенном ниже примере (предоставим вам собственный вспомогательный класс, если вы не хотите импортировать эту библиотеку), чтобы сериализовать/десериализовать на лету в/из byte[]. Не забудьте отметить «поддельный» геттер с помощью @Transcient или Hibernate попытается создать поле (и сбой, потому что он не сможет определить тип для 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); 
    } 
} 

Не забудьте сделать Person класс Serializable и добавить реальный serialVersionUID (я просто показывает по умолчанию здесь):

public class Person implements Serializable { 

    private static final long serialVersionUID = 1L; 

    // ... 

    private String firstName, lastName; 
    private int age; 

} 

Но, позвольте мне настаивать, это (изменение Person может потребовать «переноса» содержимого BLOB, чтобы избежать проблем с десериализацией, и это станет болезненным. Вы должны действительно пересмотреть эту идею и вместо этого использовать другую таблицу для Person (или я почему вы используете базу данных).

+0

почему вы не можете использовать пользователя базы данных, может быть, потому что использовать его бессмысленно? Если все, что мне нужно, это хранить список чего-то, мне не нужно помещать его в отдельную базу данных. – Enerccio

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

, если вы не можете использовать Hibernate аннотации попробовать это:

@Lob 
private Serializable familyMembers; 

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

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

Да, но это не аннотация JPA. –

+0

см. Обновление к ответу –

Смежные вопросы