Java 使用 Hibernate JPA 在列中存储对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2121860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:46:59  来源:igfitidea点击:

Storing Objects in columns using Hibernate JPA

javahibernateserializationormjpa

提问by satnam

Is it possible to store something like the following using only one table? Right now, what hibernate will do is create two tables, one for Families and one for people. I would like for the familymembers object to be serialized into the column in the database.

是否可以仅使用一张表存储如下内容?现在,hibernate 会做的是创建两张表,一张用于家庭,一张用于人。我希望将 familymembers 对象序列化到数据库中的列中。

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

    private final List<Person> familyMembers;

}

class Person{

   String firstName, lastName;
   int age;

}

回答by Ondra ?i?ka

You can create pseudoproperty (getter and setter) which accepts/returns the serialized form, and annotate the familyMemberswith @Transient. This would also need to annotate the getters, not fields, for all other properties.

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

回答by Bozho

Annotate the property with @Columnand define the type to be ArrayList, not just List. And make Personimplement Serializable.

使用 注释属性@Column并将类型定义为ArrayList,而不仅仅是List. 并使Person实施Serializable

But you should do this only if your motives are very clear, because this is the correct solution in some very rare cases. As Pascal noted, if you ever have to change Personyou'll have headaches.

但是只有在您的动机非常明确时才应该这样做,因为在一些非常罕见的情况下这是正确的解决方案。正如 Pascal 所说,如果你不得不改变,Person你会很头疼。

回答by Pascal Thivent

This is an horrible design and I'm really not recommending it (you should just create another table) but it is possible.

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

First, you'll need to use a byte[]attribute to hold a serialized version of the list of persons that will be stored in a BLOB in the database. So annotate it's getter with @Lob(I would make the getter and setter privateto not expose them). Then, expose "fake" getter and setter to return or set a List<Person>from the byte[]. I'm using SerializationUtilsfrom Commons Lang in the sample below (provide you own helper class if you don't want to import this library) to serialize/deserialize on the fly to/from the byte[]. Don't forget to mark the "fake" getter with @Transcientor Hibernate will try to create a field (and fail because it won't be able to determine the type for a List).

首先,您需要使用一个byte[]属性来保存将存储在数据库的 BLOB 中的人员列表的序列化版本。所以注释它的 getter @Lob(我会让 getter 和 setterprivate不暴露它们)。然后,公开“假”getter 和 setter 以List<Person>byte[]. 我在SerializationUtils下面的示例中使用from 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);
    }
}

Don't forget to make the Personclass Serializableand to add a real serialVersionUID(I'm just showing a default here):

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

public class Person implements Serializable {

   private static final long serialVersionUID = 1L;

   // ...

   private String firstName, lastName;
   private int age;

}

But, let me insist, this is an horrible design and it will be very fragile (changing Personmight require to "migrate" the content of the BLOB to avoid deserialization issues and this will become painful. You should really reconsider this idea and use another table for the Personinstead (or I don't get why you use a database).

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

回答by Sergey Demin

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

if you can't use hibernate annotations try this:

如果您不能使用休眠注释,请尝试以下操作:

@Lob
private Serializable familyMembers;

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

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