Hello,
I have rather weird problem accessing legacy database schema and I'm not able to figure out what would be the correct solution.
The database is like the following:
There are three tables - Rule, RuleSet and RuleDefinition, that are defined as follows:
create table Rule (rule_id int, ...)
create table RuleSet (rule_id int, ruledefinition_id int, bind_key int)
create table RuleDefinition (ruledefinition_id int, ...)
The application I use use RuleDefinition only in read-only mode. They can't be modified. The primary purpose is to create/edit/delete entries in Rule table and to create/edit/delete entries in RuleSet table mapping those Rules N:N with RuleDefinitions.
I use the following mapping files:
---- Rule.hbm.xml: ----
<hibernate-mapping default-access="field">
<class name="Rule" table="RULE" optimistic-lock="all" dynamic-update="true" dynamic-insert="true">
<id name="id" column="RULE_ID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">RULE_SEQ</param>
</generator>
</id>
<!-- more simple properties are here -->
<set name="ruleSets" order-by="BIND_KEY" cascade="delete,save-update" inverse="true">
<key column="RULE_ID" />
<one-to-many class="RuleSet" />
</set>
</hibernate-mapping>
---- end of Rule.hbm.xml: ----
---- RuleSet.hbm.xml: ----
<hibernate-mapping default-access="property">
<class name="RuleSet" table="RULESET">
<composite-id>
<key-many-to-one name="rule" class="Rule" column="RULE_ID" />
<key-many-to-one name="ruleDefinition" class="RuleDefinition" column="RULEDEFINITION_ID" lazy="false" />
<key-property name="bindKey" column="BIND_KEY" />
</composite-id>
</class>
</hibernate-mapping>
---- end of RuleSet.hbm.xml: ----
---- RuleDefinition.hbm.xml: ----
<hibernate-mapping default-access="field">
<class name="RuleDefinition" table="RULEDEFINITION" optimistic-lock="all" dynamic-update="true" dynamic-insert="true">
<id name="id" column="RULEDEFINITION_ID" unsaved-value="0">
<generator class="sequence">
<param name="sequence">RULEDEFINITION_SEQ</param>
</generator>
</id>
<!-- more simple properties are here -->
</class>
</hibernate-mapping>
---- end of RuleDefinition.hbm.xml: ----
Please ignore, if there are any apparent typos in the declaration, I shortened some of the declarations and gave them readable names of classes and tables. The classes themselves are simple containers for data with getters and setters as expected. Now the problem is as this:
The user opens dialog for editation of Rule and he is presented with fields to edit details of Rule and to edit associations between Rule and RuleDefinition (represented by RuleSet table). I want him to be able to make whatever intermediate changes he wants (including for example dissociating Rule and RuleDefinition and reassociating it again) and after the user presses Save, the difference between the saved state and the new should be saved.
The approach I use is, that whenever the user changes any mapping, it is:
1) deleted from session
Code:
getSession().delete(RuleSet)
RuleSet.getRule().getRuleSets().remove(RuleSet))
2) new one is inserted
Code:
new RuleSet()
fill it in
getSession().save(RuleSet)
RuleSet.getRule().getRuleSets().add(RuleSet)))
There are several usecases which cause problems:
1) User opens the dialog, changes one association and than changes it back. This provokes inserts and deletes into database even though the session has not yet been flushed. This means, that when the user presses cancel button, the state in database has already been somehow altered.
I would like to ask somebody with more experience to hint me on what the correct values are for attributes like "cascade" and "inverse" and how to do the object model mangling (when to do save() and delete()) so that the Cancel/Save button works correctly (cancel is supposed to reload from DB, Save is supposed to commit changes from the UI into database).
Namely, I have came up with two possible courses of action:
1) reimplement RuleSet so that it uses composite key.
2) do not call save() and delete() on RuleSets while the user is editing them, but only collect list of Rules that have changed and at the end delete all RuleSets, flush() and recreate them again and flush(). this would produce delete and insert statements necessary. I'm afraid here, that if the application fails in the middle, the database might be left deleted :-(
Do you think that my plans will work? Do you have any other ideas? I've tried lots of configuration tweaks already and still, some usecases (create Rule, change various combinations of RuleSet, change and undo changes of RuleSets) don't work...
thanks!
Kuba
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version:
Mapping documents:
Code between sessionFactory.openSession() and session.close():
Full stack trace of any exception that occurs:
Name and version of the database you are using:
The generated SQL (show_sql=true):
Debug level Hibernate log excerpt:
Problems with Session and transaction handling?
Read this:
http://hibernate.org/42.html