Hello,
We have upgraded an application from Hibernate 2.1.6 to Hibernate 3.0rc1. It works perfectly, but now we want to use the new XML Mapping feature for generating several reports and we are experiencing a problem.
For testing purposes, we have the following two hbm files:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.ph.dto.TipoViviendaDto" table="TIPOVIVIENDA" lazy="false">
<cache usage="read-write"/>
<id name="id" type="java.lang.Integer" unsaved-value="null" node="@id">
<column name="ID" not-null="true"/>
<generator class="increment"/>
</id>
<version name="version" node="@version"/>
<property unique="true" name="nombre" type="java.lang.String" node="nombre">
<column name="NOMBRE" not-null="true"/>
</property>
</class>
</hibernate-mapping>
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.ph.dto.SubtipoViviendaDto" table="SUBTIPOVIVIENDA" lazy="false">
<cache usage="read-write"/>
<id name="id" type="java.lang.Integer" unsaved-value="null" node="@id">
<column name="ID" not-null="true"/>
<generator class="increment"/>
</id>
<version name="version" node="@version"/>
<property unique="true" name="nombre" type="java.lang.String" node="nombre">
<column name="NOMBRE" not-null="true"/>
</property>
<many-to-one name="tipoVivienda"
column="TIPOVIVIENDA"
class="com.ph.dto.TipoViviendaDto"
not-null="true"
node="tipoVivienda"
embed-xml="false"
lazy="false" />
</class>
</hibernate-mapping>
With these hbm files the program works perfectly, but when we change "embed-xml" attribute to "true" in the second hbm file (in the <many-to-one>) it doesn't work.
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.ph.dto.SubtipoViviendaDto" table="SUBTIPOVIVIENDA" lazy="false">
<cache usage="read-write"/>
<id name="id" type="java.lang.Integer" unsaved-value="null" node="@id">
<column name="ID" not-null="true"/>
<generator class="increment"/>
</id>
<version name="version" node="@version"/>
<property unique="true" name="nombre" type="java.lang.String" node="nombre">
<column name="NOMBRE" not-null="true"/>
</property>
<many-to-one name="tipoVivienda"
column="TIPOVIVIENDA"
class="com.ph.dto.TipoViviendaDto"
not-null="true"
node="tipoVivienda"
[b]embed-xml="true"[/b]
lazy="false" />
</class>
</hibernate-mapping>
This is the code between the openSession() and session.close() for querying:
Code:
...
...
Document doc = DocumentFactory.getInstance().createDocument();
Element rootNode = doc.addElement("resultado");
session = HibernateUtils.getSession();
Session xmlSession = session.openSession(EntityMode.DOM4J);
Query q = xmlSession.createQuery(hql);
if (parameters != null) {
for (int i = 0; i < parameters.size(); i++) {
q.setParameter(i, parameters.elementAt(i));
}
}
if (pageSize == Integer.MAX_VALUE)
q.setMaxResults(Integer.MAX_VALUE);
else
q.setMaxResults(pageSize + 1);
q.setFirstResult((pageCount - 1) * pageSize);
List list = q.setCacheable(true).list();
result = new Object[list.size()];
for (int i = 0; i < list.size(); i++) {
Element element = (Element) list.get(i);
rootNode.add(element);
}
...
...
The database is Derby 10.0.2.1.
The generated SQL sentences are:
Code:
Hibernate: select distinct subtipoviv0_.ID as ID, subtipoviv0_.version as version43_, subtipoviv0_.NOMBRE as NOMBRE43_, subtipoviv0_.TIPOVIVIENDA as TIPOVIVI4_43_ from SUBTIPOVIVIENDA subtipoviv0_ order by nombre , tipoVivienda
Hibernate: select tipovivien0_.ID as ID0_, tipovivien0_.version as version58_0_, tipovivien0_.NOMBRE as NOMBRE58_0_ from TIPOVIVIENDA tipovivien0_ where tipovivien0_.ID=?
Hibernate: select tipovivien0_.ID as ID0_, tipovivien0_.version as version58_0_, tipovivien0_.NOMBRE as NOMBRE58_0_ from TIPOVIVIENDA tipovivien0_ where tipovivien0_.ID=?
Hibernate: select tipovivien0_.ID as ID0_, tipovivien0_.version as version58_0_, tipovivien0_.NOMBRE as NOMBRE58_0_ from TIPOVIVIENDA tipovivien0_ where tipovivien0_.ID=?
The effect is that only a few of the entities "subtipovivienda" load the many-to-one "tipovivienda" and the resulting XML is:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<resultado>
<SubtipoViviendaDto id="2" version="0"><nombre>Adosado</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="4" version="0"><nombre>Bajo</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="6" version="0"><nombre>Dúplex</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="0" version="0"><nombre>Independiente</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="8" version="0">
<nombre>Loft</nombre>
<tipoVivienda id="2" version="13">
<nombre>Loft</nombre>
</tipoVivienda>
</SubtipoViviendaDto>
<SubtipoViviendaDto id="1" version="0">
<nombre>Pareado</nombre>
<tipoVivienda id="0" version="13">
<nombre>Chalet</nombre>
</tipoVivienda>
</SubtipoViviendaDto>
<SubtipoViviendaDto id="3" version="0"><nombre>Piso</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="5" version="0"><nombre>�tico</nombre></SubtipoViviendaDto>
<SubtipoViviendaDto id="7" version="0"><nombre>�tico dúplex</nombre>
<tipoVivienda id="1" version="13">
<nombre>Piso</nombre>
</tipoVivienda>
</SubtipoViviendaDto>
</resultado>
Then, when we try to access the attribute "tipovivienda" occurs the following exception:
Code:
java.lang.Exception: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ph.dto.SubtipoViviendaDto.tipoVivienda
at com.ph.inmobiliaria.actions.subtipovivienda.SubtipoViviendaListReportAction.execute(SubtipoViviendaListReportAction.java:43)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:484)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:274)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1482)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:507)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.securityfilter.filter.SecurityFilter.doFilter(SecurityFilter.java:182)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:186)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:825)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:731)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:526)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ph.dto.SubtipoViviendaDto.tipoVivienda
at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:163)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:190)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:70)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:669)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:298)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at com.ph.inmobiliaria.actions.subtipovivienda.SubtipoViviendaListReportAction.execute(SubtipoViviendaListReportAction.java:38)
... 23 more
Any help will be very much appreciated.
Thank you.