I'm having problems with multiple applications updating my DB when both are running. One application is an Eclipse RCP application. The other is a Spring-based web application being built up that performs some similar functionality as the RCP app.
The RCP app basically has a long running Hibernate session opened at the start. All objects and associations are lazy-loaded. Users can create n update objects in the object graph as needed. A new transaction is created for each save(), update(), delete(), etc.
For the Spring web application, I implement the basic filters as defined in the Hibernate bible, which closes the session after each request.
The RCP app has been working just fine for a year now but as I build up my Spring-based web application do some similar functionality I'm getting the (as expected) org.hibernate.StaleObjectStateException when I interleave DB operations between the two applications when both are running.
For example, a user in the Eclipse RCP app creates a record, the web user updates the record and then I go back to the Eclipse RCP and try to add a related object to my original record and I get the StaleObjectStateException.
The web application implements object fetching 'the hard way'. I fetch the objects from Hibernate as I need them. I have no problems with DB access (e.g., no Stale...) using this method.
I've tried various strategies in the data layer of my RCP application so that before I call update() on the changed object I evict() it, refresh() it, merge() it, close the session, etc. All to no avail......
Various mapping documents n code follow.
Help.....
Hibernate version:
3.1.3
Mapping documents:
An abbriviated hibernate.cfg.xml and two class mapping files follow:
Code:
<hibernate-configuration>
<session-factory>
<!-- use Jakarta DBCP -->
<property name="hibernate.connection.provider_class">com.xxx.model.dbConnection.DBCPConnectionProvider</property>
<property name="connection.pool_size">8</property>
<property name="current_session_context_class">thread</property>
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<mapping resource="Person.hbm.xml"/>
<mapping resource="Client.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Person.hbm.xml:
Code:
<hibernate-mapping package="com.xxx.model">
<class name="Person" table="PERSON">
<id name="key" column="personKey">
<generator class="native"/>
</id>
<timestamp name="Ts" column="ts" source="vm"/>
<property name="Id" type="string" column="id" length="128"/>
</class>
</hibernate-mapping>
Client.hbm.xml
Code:
<hibernate-mapping package="com.xxx.model">
<joined-subclass name="Client" extends="Person" table="CLIENT">
<key column="clientKey"/>
<set name="Sessions"
inverse="true"
cascade="all-delete-orphan"
>
<key column="clientKey"/>
<one-to-many class="Session"/>
</set>
</joined-subclass>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
session.setClient(client);
session.setId(new UUID());
client.add(session);
update(client);
Full stack trace of any exception that occurs:Code:
ERROR [main] def.AbstractFlushingEventListener - Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.tm.proXDriver.model.Client#3]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:1635)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2208)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2118)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2374)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:91)
Name and version of the database you are using:MySQL 5.0.27
The generated SQL (show_sql=true):Code:
Hibernate: update PERSON set ts=?, id=?, firstName=?, lastName=?, gender=?, email=?, phone=?, dob=?, lastSynch=?, locationKey=?, addressKey=? where personKey=? and ts=?