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.
@Entity(name = "family")
class Family{
private final List<Person> familyMembers;
}
class Person{
String firstName, lastName;
int age;
}
@Column. Let's start with the @Column annotation. It is an optional annotation that enables you to customize the mapping between the entity attribute and the database column.
Java classes whose objects or instances will be stored in database tables are called persistent classes in Hibernate. Hibernate works best if these classes follow some simple rules, also known as the Plain Old Java Object (POJO) programming model. All Java classes that will be persisted need a default constructor.
Hibernate is an implementation of JPA. Hence, the common standard which is given by JPA is followed by Hibernate. It is a standard API that permits to perform database operations. It is used in mapping Java data types with SQL data types and database tables.
Since JPA 2.0, you can use an element collection to persist a Collection of value types. You just need to annotate the attribute with @ElementCollection and the persistence provider will persist the elements of the Collection in an additional database table.
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
).
@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):
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).
@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;
}
Annotate the property with @Column
and define the type to be ArrayList
, not just List
. And make Person
implement 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With