Reputation: 165
I am not particularly familiar with hibernate or JAXB so forgive me if I dont do a great job of explaining my problem.
The program I am working with already had set up a class of hibernate entities. My job was to add JAXB annotations to marshal the variables to an XML file.
@OneToMany(fetch = FetchType.LAZY, mappedBy = "Blah")
@XmlElementWrapper(name = "ListOfThings")
@XmlElement(name = "Thing")
private Set<Stuff> stuff = new HashSet<Stuff>(0);
When I try to run the program, I get this error:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.class, no session or session was closed
I have 3 variables that I use the @XmlElement annotation with and two also have the @OneToMany annotation. Both @OneToMany variables give me that same error, but when I make them both transient, the program compiles perfectly well with the non-@OneToMany-annotated variable.
Any idea what my problem might be?
Upvotes: 0
Views: 969
Reputation: 460
There are 2 solutions to that, which can be combined in order to have finest control of marshalling.
public abstract ValueT get(BeanT bean) throws AccessorException;
and if the pojo is not initialized, return null :
if (!Hibernate.isInitialized(valueT)) {
return null;
}
Note there is an annoying optimize method :
public Accessor<BeanT,ValueT> optimize(@Nullable JAXBContextImpl context) {
return this;
}
which can replace your custom Accessor, depending on the Accessor you override (see FieldReflection).
Do not forgot the following initialization of JAXBContext :
HashMap<String, Object> props = new HashMap<String, Object>();
props.put(JAXBRIContext.XMLACCESSORFACTORY_SUPPORT, true);
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] { clazz }, props);
HashMap<String, Object> props = new HashMap<String, Object>();
props.put(JAXBRIContext.ANNOTATION_READER, new CustomAnnotationReader());
JAXBContext jaxbContext = JAXBContext.newInstance(new Class[] { clazz }, props);
RuntimeInlineAnnotationReader
is final and cannot be overriden... so you will have to copy the code.
I personnaly combined those two approches in order to modify marshalling depending on the context and content of the objects.
Upvotes: 0
Reputation: 6497
When JAXB writes the XML, it walks the whole data structure including all relationships. Hibernate is using lazy loading. You need to make sure that your entity is attached to an active hibernate session when you are having JAXB create the XML. This allows hibernate to do the required queries to fill in the lazy-loaded part of the data structure as JAXB asks for them.
Upvotes: 1