I’m new to Hibernate and looking into moving a legacy application from hand-coded persistence to Hibernate. The application uses a dynamic data model (Maps, not JavaBeans) so I’m using Hibernate’s MAP entity mode. So far my attempts require either a change to the data or to the database schema.
The essence of the problem is that in the application, map A contains an entry with map B as its value, but in the hand-coded schema, table B contains a foreign key reference to map A (i.e. reverse of the java object reference). I don’t think this is unusual; map B is optional and there is no need to clutter table A with null references to table B. This pattern is repeated several times in the application.
Hibernate generates a schema consistent with the hand-coded schema from the hbm included below.
However, executing the code below to save A and B results in these rows in the database, not preserving the association between A and B:
Code:
mysql> select * from A;
+------+
| a_id |
+------+
| 1 |
+------+
1 row in set (0.02 sec)
mysql> select * from B;
+------+------+
| b_id | a_id |
+------+------+
| 1 | NULL |
+------+------+
1 row in set (0.01 sec)
I’ve found that map B must contain an entry for map A in order for the a_id column to contain the desired reference (yes, this is what the hbm file seems to assert). But doing so would introduce a cycle in the graph of java Map objects (A->B->A...). It would also require modifying the application which is undesirable due to the prevalence of this pattern.
Can the hbm file be re-written in such a way that the association between A and B is preserved?
Hibernate version: 3.3.1 GA
Mapping documents:Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class
entity-name="AEntity"
table="A">
<id
name="a_id"
type="long"
column="a_id">
<generator class="native"/>
</id>
<one-to-one
name="b"
cascade="all"
entity-name="BEntity"
property-ref="a"/>
</class>
<class
entity-name="BEntity"
table="B">
<id
name="b_id"
type="long"
column="b_id">
<generator class="native"/>
</id>
<many-to-one
name="a"
entity-name="AEntity"
column="a_id"
unique="true"/>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():Code:
Transaction tx = session.beginTransaction();
Map a = new HashMap();
Map b = new HashMap();
a.put("b", b);
Long aId = (Long) session.save("AEntity", a);
tx.commit();
Name and version of the database you are using: MySQL 5.0