10

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;

}
3
  • This is not clear. If you're seeing familly as a group of person, then you need a new table for familly, except if you represent the familly with a simple type like an integer or a string. Commented Jan 23, 2010 at 2:55
  • 1
    OT: That would be a bad design. Commented Jan 23, 2010 at 3:59
  • If a family has 3 members, what value would you expect to see in the database column? Commented Jan 23, 2010 at 4:37

4 Answers 4

14

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).

Sign up to request clarification or add additional context in comments.

1 Comment

why can't you use database person, maybe because using it is pointless? If all I need is store a list of something, I don't need to put it in separate database.
4
@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;
}

1 Comment

Yes, but This is not a JPA annotation.
1

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.

2 Comments

I'm pretty sure that this would fail with a java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.sql.Blob
yes, I took a look at one class of mine where I'm having the same situation - it works withotu Lob, and with specifying the concrete type (ArrayList). Updated the answer
0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.