Hi! I'm working on a program to store and manage test results. Tests have properties like date, duration, and also results. However, some tests measure pressure, others temperature... I hope you get the idea. So, not every test has the same attributes.
My first thought was to extract the test results out of the test table into individual result tables, thus creating a 1:1 relationship. And to keep the test results extensible, I wanted to have the results stored in Maps rather than Beans.
However, it seems that Hibernate doesn't like my approach. Does anyone have Experience with this kind of mapping? Is there a better alternative?
EDIT for Example and further explanation
--------
| Test |
|id |
+--------+
|date |
|duration| 1 1 ----------
|... | --------- | Medium |
-------- |testID |
+----------+
|medium |
|pressure |
----------
Medium would be one property that a test can have. As other properties could be added, I don't want to hardcode the Medium class but rather map it as a Map, storing the three attributes. My thought was that Test would have a Map<String, Map<String, Object>>
to represent all properties associated with it.
<?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 package="com.hoerbiger.versuchsdb.domain">
<class name="Test" lazy="false">
<id name="id">
<generator class="native"/>
</id>
<property name="datum"/>
<many-to-one name="material" class="Material"/>
<set name="testgeraete" table="Test_Testgeraet" lazy="false">
<key column="testID"/>
<many-to-many column="geraetID" class="Testgeraet"/>
</set>
<!-- Here it's getting important -->
<one-to-one name="medium" entity-name="Medium" constrained="false" lazy="false"
access="com.hoerbiger.versuchsdb.hibernate.TestAccessor"/>
</class>
</hibernate-mapping>
Where the com.hoerbiger.versuchsdb.hibernate.TestAccessor
is a PropertyAccessor to access the map that I want to use for the relations
<?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 package="com.hoerbiger.versuchsdb.domain">
<class entity-name="Medium" lazy="false">
<id name="id" type="long">
<generator class="foreign">
<param name="property">id</param>
</generator>
</id>
<one-to-one name="id" class="Test" constrained="true"/>
<property name="medium" type="string"/>
<property name="pressure" type="int"/>
</class>
</hibernate-mapping>
To try what works, I used this main method. Note the last few lines
@SuppressWarnings("unchecked")
public static void main(String[] args) {
Session s = Helper.getSessionfactory().getCurrentSession();
s.beginTransaction();
//Change to dynamic session
s = s.getSession(EntityMode.MAP);
Map<String, Object> test = (Map<String, Object>) s.createQuery("from Test").iterate().next();
//for me, prints "25"
System.out.println(test.get("id"));
Map<String, Object> medium = new HashMap<String, Object>();
medium.put("id", test);
medium.put("medium", "Luft");
medium.put("pressure", 40);
s.save("Medium", medium);
s.getTransaction().commit();
System.out.println("---");
s = Helper.getSessionfactory().getCurrentSession();
s.beginTransaction();
Test t = (Test) s.createQuery("from Test").iterate().next();
//for me, prints "null, 2010-07-07 00:00:00.0" (Test.toString())
System.out.println(t);
//"25"
System.out.println(t.getId());
//"{medium={id=null, 2010-07-07 00:00:00.0, ...}}"
System.out.println(t.getProperties());
//"true"
System.out.println(t.getProperties().get("medium").get("id") == t);
//This is really weird - hibernate loads the map with a Test stored, but when
//saving, it expects a Long. With this line, the Commit succeeds
t.getProperties().get("medium").put("id", t.getId());
s.getTransaction().commit();
}
What's up with these last lines? Is it a bug in hibernate or a misconfiguration?