Hi there,
I'm going through the Java Persistence with Hibernate book. I know there is a forum for that, but IMO this is more to do with general hibernate usage.
Please note this is
not a critical issue for me: rather I am just curious to know if this is a genuine bug, or just a case of RTFM?
Everything is working fine, until I tried to mix
union-subclass with
DOM4J output.
I am currently investigating class inheritance using a table per concrete class with unions (section 5.1.2).
My hbm mapping file looks fine:
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 package="org.nkl.model">
<class name="BillingDetails" abstract="true">
<id name="id" column="BILLING_DETAILS_ID">
<generator class="sequence" />
</id>
<property name="owner" />
<union-subclass name="CreditCard" table="CREDIT_CARDS">
<property name="number" />
<property name="expiryMonth" column="EXP_MONTH" />
<property name="expiryYear" column="EXP_YEAR" />
</union-subclass>
<union-subclass name="BankAccount" table="BANK_ACCOUNTS">
<property name="account" />
<property name="bankName" />
<property name="swift" />
</union-subclass>
</class>
</hibernate-mapping>
My unit test works fine:
Code:
package org.nkl;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.nkl.model.Address;
import org.nkl.model.CreditCard;
import org.nkl.model.User;
public class BasicTest {
private static SessionFactory sessionFactory;
@AfterClass
public static void afterClass() {
HibernateUtil.shutdown();
}
@BeforeClass
public static void beforeClass() {
sessionFactory = HibernateUtil.getSessionFactory();
}
@Test
public void testMessage() throws Exception {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
User user = new User("John", "Smith");
user.setHomeAddress(new Address("10 Downing Street", "LND1",
"Westiminster"));
user.setBillingAddress(new Address("10 Downing Street", "LND1",
"Westiminster"));
user.setBillingDetails(new CreditCard(user.getLastName(), "000", "12",
"2009"));
// user.getBillingDetails().setId(0L);
Long userId = (Long) session.save(user);
tx.commit();
session.close();
session = sessionFactory.openSession();
tx = session.beginTransaction();
List users = session.createQuery("from User u order by u.lastName asc")
.list();
System.out.println(users.size() + " user(s) found");
for (Object o : users) {
User u = (User) o;
System.out.printf("%s, %s%n", u.getLastName(), u.getFirstName());
}
tx.commit();
session.close();
// UNCOMMENT TO SEE ISSUE:
//
// session = sessionFactory.openSession();
// tx = session.beginTransaction();
// Session dynamicSession = session.getSession(EntityMode.DOM4J);
// Element userXml = (Element) dynamicSession.load(User.class, userId);
// OutputFormat outputFormat = OutputFormat.createPrettyPrint();
// XMLWriter xmlWriter = new XMLWriter(System.out, outputFormat);
// xmlWriter.write(userXml);
// tx.commit();
// session.close();
}
}
However, when I uncomment the lines where I read in the User entity as a DOM4J element, I get the following stacktrace:
Code:
org.hibernate.HibernateException: instance not of expected entity type: org.hibernate.tuple.ElementWrapper is not a: org.nkl.model.BillingDetails
at org.hibernate.persister.entity.AbstractEntityPersister.getSubclassEntityPersister(AbstractEntityPersister.java:3663)
at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1374)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:203)
at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:241)
at org.hibernate.type.EntityType.getIdentifier(EntityType.java:430)
at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:265)
at org.hibernate.type.TypeFactory.findDirty(TypeFactory.java:619)
at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3151)
at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:501)
at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:227)
at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:150)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219)
at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:49)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1027)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:370)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at org.nkl.BasicTest.testMessage(BasicTest.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997)
My Maven POM file contains:
Code:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>3.3.1.GA</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
</dependency>
<dependency>
<groupId>hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>1.8.0.7</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.8.0.GA</version>
</dependency>
</dependencies>