使用Hibernate JPA在列中存储对象

sat*_*nam 8 java orm serialization hibernate jpa

是否可以仅使用一个表存储类似下面的内容?现在,hibernate将做的是创建两个表,一个用于家庭,一个用于人.我想将familymembers对象序列化到数据库中的列中.

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

    private final List<Person> familyMembers;

}

class Person{

   String firstName, lastName;
   int age;

}
Run Code Online (Sandbox Code Playgroud)

Pas*_*ent 13

这是一个可怕的设计,我真的不推荐它(你应该创建另一个表),但它是可能的.

首先,您需要使用一个byte[]属性来保存将存储在数据库中的BLOB中的人员列表的序列化版本.所以注释它的getter @Lob(我会让getter和setter private不暴露它们).然后,揭露"假" getter和setter返回或设置一个List<Person>byte[].我在SerializationUtils下面的示例中使用Commons Lang(如果您不想导入此库,则提供您自己的帮助类),以便快速序列化/反序列化byte[].不要忘记标记"假"的getter @Transcient或者Hibernate会尝试创建一个字段(并且因为它无法确定a的类型而失败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);
    }
}
Run Code Online (Sandbox Code Playgroud)

不要忘记创建PersonSerializable并添加一个真实的serialVersionUID(我只是在这里显示默认值):

public class Person implements Serializable {

   private static final long serialVersionUID = 1L;

   // ...

   private String firstName, lastName;
   private int age;

}
Run Code Online (Sandbox Code Playgroud)

但是,让我坚持,这是一个可怕的设计,它将非常脆弱(改变Person可能需要"迁移"BLOB的内容,以避免反序列化问题,这将变得痛苦.你应该真的重新考虑这个想法,并使用另一个表对于Person代替(或我不知道为什么你使用一个数据库).


Ond*_*žka 0

您可以创建接受/返回序列化形式的伪属性(getter 和 setter),并使用 进行familyMembers注释@Transient。这还需要为所有其他属性注释 getter,而不是字段。