I am using dynamic-map persistence.
I have a mapping with subclass elements and a discriminator.
Queries execute just fine and return me a logical Map with the right elements for each subclass.
However, when I try to create a new Map and persist it, I get "org.hibernate.HibernateException: instance not of expected entity type: Entity", Entity being the superclass entity-name. I get the same message whether I specify "Entity" or one of the subclass types in sess.save(). When I remove the discriminator and subclass mappings, I can persist objects of the superclass type w/ no problem.
(How would Hibernate even know that the instance is not of the right type w/ dynamic-map strategy?)
(More info on the legacy schema, if this is helpful or anyone can recommend alternative mapping strategies:
I have a table called ACCOUNTS and a table called NAMES. ACCOUNTS is keyed by ACCOUNT_ID; NAMES is keyed by composite ACCOUNT_ID, NAME_ID. NAME_ID=0 represents the "account name" - e.g., name of an organization, while NAME_ID>0 represents individual people on the account. I am attempting to map as follows:
superclass - Entity, which represents EITHER an account or a name (this is useful b/c other things in the system can point to either account-level or name-level entities)
subclasses:
Account - represents an account, and getNameLine returns the account name (name_id=0); allows addition of new people (not yet mapped)
Person - represents an individual person on an account (name_id>0)
So I thought it would make sense to make the primary table of the mapping NAMES (even though ACCOUNTS is the parent table - every ACCOUNT must have a NAME_ID=0 record in NAMES), and have the Person subclass get additional Person-specific fields from NAMES, and have the Account subclass join to ACCOUNTS to get account-specific info.
As I said, this works beautifully when querying - it just won't persist a new Map.)
Next step for me is going to be to create concrete classes and switch back to POJO to see if the problem is really my mapping or if it's related to using dynamic-map mode.
Hibernate version:3.0
Mapping documents:
entity.hbm.xml
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 schema="PBDS" package="com.tsi.ta.model.persistence.entity.core">
<class entity-name="Entity" table="NAMES">
<composite-id name="entityId">
<key-property name="accountId" column="ACCOUNT_ID" type="integer"/>
<key-property name="nameId" column="NAME_ID" type="integer"/>
</composite-id>
<discriminator column="NAME_ID" type="string" formula="CASE WHEN NAME_ID=0 THEN 'A' ELSE 'P' END"/>
<!--discriminator column="STAFF" type="string"/-->
<property name="nameLine" column="NAME_LINE" type="string"/>
<property name="alphaName" column="ALPHA_NAME" type="string"/>
<property name="userInserting" column="USER_INSERTING" type="string"/>
<property name="dateInserted" column="DATE_INSERTED" type="calendar_date"/>
<property name="userUpdating" column="USER_UPDATING" type="string"/>
<property name="dateUpdated" column="DATE_UPDATED" type="calendar_date"/>
<property name="comments" column="COMMENTS" type="string"/>
<many-to-one name="status" entity-name="Status" lazy="false">
<column name="STS"/>
<formula>'AC'</formula>
</many-to-one>
<subclass entity-name="com.tsi.ta.model.persistence.entity.core.Account" discriminator-value="A">
<join table="TY_ACCOUNTS">
<key>
<column name="ACCOUNT_ID"/>
<column name="NAME_ID"/>
</key>
<property name="accountType" column="ACCOUNT_TYPE" type="string"/>
<property name="affiliation" column="AFFILIATION" type="string"/>
</join>
</subclass>
<subclass entity-name="com.tsi.ta.model.persistence.entity.core.Person" discriminator-value="P">
<property name="title" column="TITLE" type="string"/>
<property name="firstName" column="FIRST_NAME" type="string"/>
<property name="middleName" column="MIDDLE_NAME" type="string"/>
<property name="lastName" column="LAST_NAME" type="string"/>
<property name="suffix" column="SUFFIX" type="string"/>
</subclass>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
t = s.beginTransaction();
Map e = new HashMap();
//I've tried lots of different things in here, always w/ the same result.
s.save("com.tsi.ta.model.persistence.entity.core.Person",e);
t.commit();
Full stack trace of any exception that occurs:Code:
org.hibernate.HibernateException: instance not of expected entity type: Entity
at org.hibernate.persister.entity.BasicEntityPersister.getSubclassEntityPersister(BasicEntityPersister.java:2986)
at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1089)
at org.hibernate.id.Assigned.generate(Assigned.java:31)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:85)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:184)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:173)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:69)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:480)
at com.tsi.ta.test.model.Tester3.testPersist(Tester3.java:133)
at com.tsi.ta.test.model.Tester3.main(Tester3.java:144)
Name and version of the database you are using:Oracle 9.2.0.6.0
The generated SQL (show_sql=true):N/A
Debug level Hibernate log excerpt:Code:
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: com\tsi\ta\model\persistence\entity\core\mappings\Entity.hbm.xml
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: Entity -> NAMES
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: com.tsi.ta.model.persistence.entity.core.Account -> NAMES
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindJoin
INFO: Mapping class join: com.tsi.ta.model.persistence.entity.core.Account -> TY_ACCOUNTS
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindSubclass
INFO: Mapping subclass: com.tsi.ta.model.persistence.entity.core.Person -> NAMES
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: com\tsi\ta\model\persistence\core\mappings\Status.hbm.xml
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: Status -> SYSTEM_STATUS
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindCompositeId
WARNING: Could not perform validation checks for component as the class com.tsi.ta.model.persistence.core.CompositeCode was not found
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration addResource
INFO: Mapping resource: com\tsi\ta\model\persistence\core\mappings\StatusType.hbm.xml
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.HbmBinder bindRootPersistentClassCommonValues
INFO: Mapping class: StatusType -> STATUS_TYPE
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing extends queue
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing collection mappings
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing association property references
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.Configuration secondPassCompile
INFO: processing foreign key constraints
Sep 12, 2005 5:25:47 PM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Using Hibernate built-in connection pool (not for production use!)
Sep 12, 2005 5:25:47 PM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: Hibernate connection pool size: 20
Sep 12, 2005 5:25:47 PM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: autocommit mode: false
Sep 12, 2005 5:25:47 PM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: using driver: oracle.jdbc.driver.OracleDriver at URL: jdbc:oracle:thin:@linuxdev01-vhost1:1521:lnx1
Sep 12, 2005 5:25:47 PM org.hibernate.connection.DriverManagerConnectionProvider configure
INFO: connection properties: {user=pbds , password=****}
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: RDBMS: Oracle, version: Oracle9i Release 9.2.0.6.0 - Production
JServer Release 9.2.0.6.0 - Production
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC driver: Oracle JDBC driver, version: 9.0.1.5.0
Sep 12, 2005 5:25:47 PM org.hibernate.dialect.Dialect <init>
INFO: Using dialect: org.hibernate.dialect.OracleDialect
Sep 12, 2005 5:25:47 PM org.hibernate.transaction.TransactionFactoryFactory buildTransactionFactory
INFO: Using default transaction strategy (direct JDBC transactions)
Sep 12, 2005 5:25:47 PM org.hibernate.transaction.TransactionManagerLookupFactory getTransactionManagerLookup
INFO: No TransactionManagerLookup configured (in JTA environment, use of read-write or transactional second-level cache is not recommended)
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic flush during beforeCompletion(): disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Automatic session close at end of transaction: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch size: 15
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC batch updates for versioned data: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Scrollable result sets: enabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: JDBC3 getGeneratedKeys(): disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Connection release mode: null
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default batch fetch size: 1
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Generate SQL with comments: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Order SQL updates by primary key: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory createQueryTranslatorFactory
INFO: Query translator: org.hibernate.hql.ast.ASTQueryTranslatorFactory
Sep 12, 2005 5:25:47 PM org.hibernate.hql.ast.ASTQueryTranslatorFactory <init>
INFO: Using ASTQueryTranslatorFactory
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query language substitutions: {}
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Second-level cache: enabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Query cache: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory createCacheProvider
INFO: Cache provider: org.hibernate.cache.EhCacheProvider
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Optimize cache for minimal puts: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Structured second-level cache entries: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Echoing all SQL to stdout
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Statistics: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Deleted entity synthetic identifier rollback: disabled
Sep 12, 2005 5:25:47 PM org.hibernate.cfg.SettingsFactory buildSettings
INFO: Default entity-mode: dynamic-map
Sep 12, 2005 5:25:47 PM org.hibernate.impl.SessionFactoryImpl <init>
INFO: building session factory
Sep 12, 2005 5:25:47 PM org.hibernate.impl.SessionFactoryObjectFactory addInstance
INFO: Not binding factory to JNDI, no JNDI name configured
Sep 12, 2005 5:25:47 PM org.hibernate.impl.SessionFactoryImpl checkNamedQueries
INFO: Checking 0 named queries