trying to familiarise myself with with eclipse and hibernate.
I am running the jboss eclipse build with hibernate r3b4.
couple of issues.
1 I am trying to use inheritance with with concrete table per subclass (union-subclass) and an abstract base class.
my database is MySQL 4.1
I have tried to create an asbtract base class with generator = increment defined in the base, and a concrete subclass that inherits.
here is the mapping file
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">
<!--
This mapping demonstrates how to use a composite
element mapping to model a parent/child association.
-->
<hibernate-mapping package="inventory">
<class name="Element" table="Element" abstract="true">
<id name="id" type = "long" column="ID" unsaved-value="0" >
<generator class="increment"/>
</id>
<version name="version"
type="int"
column="version"/>
<property name="key" type = "java.lang.Long" column="uniqueKey" unique="true" update="false" access="field"/>
<property name="name" type = "java.lang.String" column="name" length="100" />
<property name="nameAlias" type = "java.lang.String" column="nameAlias" length="100" />
<map name="flexAtt" table="AttVals" cascade="all">
<key column="id"/>
<map-key column="attribute" type="java.lang.String"/>
<element column="value" type="java.lang.String"/>
</map>
<union-subclass name="VirtualNetwork" table="VirtualNetwork" extends="Element">
<property name="bandwidth" type = "java.lang.String" column="bandwidth" length="30"/>
<property name="VCI" type = "java.lang.String" column="vci" length="30"/>
<property name="VPI" type = "java.lang.String" column="vpi" length="30"/>
</union-subclass>
</class>
<!--
<dynamic-class entity-name="FlexAttVals">
<id name="id" type="long" column="ID">
<generator class="native"/>
</id>
<property name="attribute" type = "java.lang.Long" column="attribute" length="50"/>
<property name="value" type = "java.lang.String" column="value" length="500" />
<many-to-one name="parent" column="parentID" class="FlexAttVals"/>
<bag name="children" inverse="true" lazy="false" cascade="all">
<key column="parentID"/>
<one-to-many class="FlexAttVals"/>
</bag>
</dynamic-class> -->
</hibernate-mapping>
when I run the test code I get the following error. Essentially this is trying to access the element table in the DB, where one does not exist as I have declared both the mapping and the java base class to be 'abstract'
Code:
48640 [main] DEBUG org.hibernate.id.IncrementGenerator - fetching initial value: select max(ID) from Element
48660 [main] DEBUG org.hibernate.util.JDBCExceptionReporter - could not fetch initial value [select max(ID) from Element]
java.sql.SQLException: Table 'test.element' doesn't exist
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2851)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1534)
at com.mysql.jdbc.ServerPreparedStatement.serverPrepare(ServerPreparedStatement.java:1485)
at com.mysql.jdbc.ServerPreparedStatement.<init>(ServerPreparedStatement.java:151)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:1309)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:1281)
at org.hibernate.id.IncrementGenerator.getNext(IncrementGenerator.java:69)
at org.hibernate.id.IncrementGenerator.generate(IncrementGenerator.java:43)
at org.hibernate.event.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:84)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:180)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:169)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:65)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:466)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:461)
at persistence.HibernatePersistenceManager.add(HibernatePersistenceManager.java:148)
at hibernatedemo.DemoDB.main(DemoDB.java:73)
48670 [main] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 1146, SQLState: 42S02
48680 [main] ERROR org.hibernate.util.JDBCExceptionReporter - Table 'test.element' doesn't exist
Exception in thread "main" java.lang.RuntimeException: could not fetch initial value
at persistence.HibernatePersistenceManager.add(HibernatePersistenceManager.java:153)
at hibernatedemo.DemoDB.main(DemoDB.java:73)
Caused by: org.hibernate.exception.SQLGrammarException: could not fetch initial value
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:70)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.IncrementGenerator.getNext(IncrementGenerator.java:90)
at org.hibernate.id.IncrementGenerator.generate(IncrementGenerator.java:43)
at org.hibernate.event.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:84)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:180)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:169)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:92)
at org.hibernate.event.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:65)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:466)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:461)
at persistence.HibernatePersistenceManager.add(HibernatePersistenceManager.java:148)
... 1 more
Caused by: java.sql.SQLException: Table 'test.element' doesn't exist
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2851)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1534)
at com.mysql.jdbc.ServerPreparedStatement.serverPrepare(ServerPreparedStatement.java:1485)
at com.mysql.jdbc.ServerPreparedStatement.<init>(ServerPreparedStatement.java:151)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:1309)
at com.mysql.jdbc.Connection.prepareStatement(Connection.java:1281)
at org.hibernate.id.IncrementGenerator.getNext(IncrementGenerator.java:69)
... 10 more
The top of this abstract class is declared as
Code:
package inventory;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
public abstract class Element
{
static Logger logger = Logger.getLogger(Element.class);
protected long id; //DB pkey column
protected long key; // internal unique key
protected String name;
protected String nameAlias;
protected int version;
protected Map<String,String> flexAtt = new HashMap<String, String>();
....
If I remove the abstract statement from the base class mapping I get two tables created in the DB, however when I run the test code to insert records for the virtual network object (my concrete class) the ID column, in the database pkey is always set to 1, and does not increment which the generator id declaration in the base class should do for me.
The generator works fine for non inherited classes mapped and I get a nice incrementing seq of id for standalone non inherited classes.
2. Second problem is I appear to have misunderstood how the <map> element should work can anyone help.
I have declared a Map element in my base class to hold tags and values, which i wanted inheriated into the concrete sub classes.
in the mapping I set the map to point to the AttVals table, set the key (to be the id field of the owning table, and created the 'attribute' map-key and 'value' element tag.
This appears to create a table okay, however when I build the instances in the code and then persist them with my persistence manager class (pm).
i get a constraint error. Looking at the database table for the attval, the id field is set with a FK constraint pointing to the element table (now that I have had to make this concrete in the mapping). whereas the hash is being used on a subclass and no record is inserted into the element table which i think is causing the error.
Code:
6379 [main] DEBUG org.hibernate.impl.SessionImpl - after transaction completion
Exception in thread "main" java.lang.RuntimeException: Could not execute JDBC batch update
at persistence.HibernatePersistenceManager.add(HibernatePersistenceManager.java:153)
at hibernatedemo.DemoDB.main(DemoDB.java:73)
Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:74)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:162)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
at org.hibernate.event.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:271)
at org.hibernate.event.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:24)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:719)
at persistence.HibernatePersistenceManager.dispose(HibernatePersistenceManager.java:110)
at persistence.HibernatePersistenceManager.add(HibernatePersistenceManager.java:149)
... 1 more
Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails
at com.mysql.jdbc.ServerPreparedStatement.executeBatch(ServerPreparedStatement.java:827)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:58)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:155)
... 8 more
How can I inherit classes and correctly get a generic map attribute to work through inheritance.
Any help would be greatfully received.