Hi,
I have been trying for quite some time to map the following hierarchy but with no success.
I have the following (simplified) class hierarchy:
- A PersistentLine class, that extends Line2D.Double with an id property
- An PersistentArc class, that extends Arc2D.Double with an id property
Both PersistentLine and PersistentArc implement a very basic interface:
Code:
public interface PersistentElement {
public void setId(Long id);
public Long getId();
}
I have, then, a class called Geometry, that contains a List of such elements (simplified):
Code:
@Entity
public class Geometry {
private List<PersistentElement> elementList;
}
As you can see, the List is a List of an interface, not a concrete class, and this is the problem that I can't seem to solve. So far, the only way that I was able to find to map this is to annotate it using @Lob, so that the collection is serialized. However, this approach has shown to be possibly very dangerous because the concrete classes that make up the collection are subject to change in the future, and I am really concerned with InvalidClassExceptions due to unmatchin serialVersionUID's.
However, I have found no successful way to map this collection. Please keep in mind that the PersistenLine and PersistenArc are well-mapped, and work perfectly when persisted as single entities, so posting the mappings here is quite useless.
Here's what happens:
What I tried to do is the following:
Code:
@Entity
public class Geometry {
@OneToMany
private List<PersistentElement> elementList;
}
The above code won't work unless PersistentElement is declared as @Entity, as expected. If I add @Entity, however, Hibernate crashes with a NullPointerException here:
Code:
java.lang.NullPointerException
at org.hibernate.cfg.AnnotationConfiguration.orderAndFillHierarchy(AnnotationConfiguration.java:101)
at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:445)
at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:268)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1286)
The code that causes the NullPointerException is the following:
== File: AnnotationConfiguration.java ==
Code:
protected List<XClass> orderAndFillHierarchy(List<XClass> original) {
//TODO remove embeddable
List<XClass> copy = new ArrayList<XClass>( original );
//for each class, copy all the relevent hierarchy
for ( XClass clazz : original ) {
XClass superClass = clazz.getSuperclass();
while ( ! reflectionManager.equals( superClass, Object.class ) && ! copy.contains( superClass ) ) {
if ( superClass.isAnnotationPresent( Entity.class )
|| superClass.isAnnotationPresent( MappedSuperclass.class ) ) {
copy.add( superClass );
}
superClass = superClass.getSuperclass();
}
}
List<XClass> workingCopy = new ArrayList<XClass>( copy );
List<XClass> newList = new ArrayList<XClass>( copy.size() );
while ( workingCopy.size() > 0 ) {
XClass clazz = workingCopy.get( 0 );
orderHierarchy( workingCopy, newList, copy, clazz );
}
return newList;
}
Specifically, the error is here:
Code:
if ( superClass.isAnnotationPresent( Entity.class )
....
Of course, superClass is null since clazz is an interface and has no superclass.
I have not submitted this on Jira because I am not sure if this is a bug in the code of Hibernate AnnotationConfiguration, or if I am the one wrong, thinking that a collection of elements of an interface can actually be mapped. Normally, the user is 98% of the times the one who's wrong so I posted here.
I don't understand what would the difference be between mapping a collection of an abstract class and a collection of a interface be, but maybe - again - it is likely that there is something that I am not seeing.
In my specific case, there is no way I can make my code fall back into the case of a List<AbstracClass> simply because my classes have different hierarchies, being one a subclass of java.awt.Line2D, and the other of java.awt.Arc2D.
At the current time I am stuck with the @Lob persistence strategy, which in many ways is undesirabile.
I hope that by posting this message as being "Emmanuel-targeted", I will be able to catch your attention. I felt that e-mailing you would be inappropriate, and opening a bug on JIRA could be a waste of time because this might be my mistake.
In case mapping a collection of interface elements is simply something that cannot be done, please let me know.
Please keep in mind that the actual interface is a bit different but I felt it was easier to post a simplified version of the code to avoid cluttering the post with useless code.
Thanks in advance for your time.