views:

330

answers:

2
@Entity
public class A {
    @Column(name="Foos")
    @Basic
    private HashSet<Foo> fooList = new HashSet<Foo>();
}

where class Foo is nothing special, just implements Serializable.

Essentially I want to Serialize the whole HashSet to the database. This mapping works ok to persist, however when I try to load it I receive a ClassNotFoundException on Foo.

Whole Exception:

...

Caused by: org.hibernate.type.SerializationException: could not deserialize
    at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:214)
    at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:240)
    at org.hibernate.type.SerializableType.fromBytes(SerializableType.java:82)
    at org.hibernate.type.SerializableType.get(SerializableType.java:39)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)
    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)
    at org.hibernate.type.AbstractType.hydrate(AbstractType.java:81)
    at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2101)
    at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1380)
    at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1308)
    at org.hibernate.loader.Loader.getRow(Loader.java:1206)
    at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:580)
    at org.hibernate.loader.Loader.doQuery(Loader.java:701)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
    at org.hibernate.loader.Loader.doList(Loader.java:2213)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
    at org.hibernate.loader.Loader.list(Loader.java:2099)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
    at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:66)
    ... 25 more
Caused by: java.lang.ClassNotFoundException: Foo
    at com.sun.appserv.server.util.ASURLClassLoader.loadClass(ASURLClassLoader.java:129)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
    at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at java.io.ObjectInputStream.resolveClass(ObjectInputStream.java:604)
    at org.hibernate.util.SerializationHelper$CustomObjectInputStream.resolveClass(SerializationHelper.java:268)
    at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1575)
    at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1496)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1732)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at java.util.HashSet.readObject(HashSet.java:291)
    at sun.reflect.GeneratedMethodAccessor25.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
    at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1849)
    at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1753)
    at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1329)
    at java.io.ObjectInputStream.readObject(ObjectInputStream.java:351)
    at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:210)
    ... 47 more
+1  A: 

No the way you try to do it is not legal.

Try replacing with this:

@CollectionOfElements 
private HashSet<Foo> fooList = new HashSet<Foo>();

If you do this, hibernate will create additional table to store the list elements. It is similar to having @OneToMany to additional entity Foo but with much shorter syntax

Gregory Mostizky
+1. However, "similar to having @OneToMany to additional entity Foo but with much shorter syntax" is very wrong. @CollectionOfElements maps `Foo`s as component whose lifecycle is bound to owning entity; @OneToMany maps a relationship between entities whose lifecycles are generally independent (though dependency can be emulated via appropriate code and cascade settings)
ChssPly76
Nope, same error.
gjrwebber
ClassNotFound? That's probably deployment/build related - doesn't have much to do with hibernate. Are you sure that Foo is in the classpath when you are running your example? After you fix that, the above solution should work.
Gregory Mostizky
I know, it is baffling. Foo is in the classpath as I can persist the HashSet perfectly well before retrieving it.
gjrwebber
I am not sure but you might be able to persist an EMPTY HashSet. Since generics are removed during compilation it might be able to persist an empty set without actually needing Foo class. As soon as it needs to load it though it would require the class definition and then it breaks.
Gregory Mostizky
A: 

It turns out it was an issue with the grizzly classloader in Glassfish. It had nothing to do with the hibernate mapping. Though hibernate still might contribute to the cause at a lower level.

gjrwebber