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
Storing Objects in columns using Hibernate JPA
提问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 familyMembers
with @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 @Column
and define the type to be ArrayList
, not just List
. And make Person
implement 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 Person
you'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 private
to not expose them). Then, expose "fake" getter and setter to return or set a List<Person>
from the byte[]
. I'm using SerializationUtils
from 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 @Transcient
or 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 Person
class Serializable
and to add a real serialVersionUID
(I'm just showing a default here):
不要忘记创建Person
类Serializable
并添加一个真实的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 Person
might 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 Person
instead (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;
}