我正在开发一个存储和管理测试结果的程序。测试具有日期,持续时间和结果等属性。然而,一些测试测量压力,其他测试温度......我希望你能得到这个想法。因此,并非每个测试都具有相同的属性。
我的第一个想法是将测试表中的测试结果提取到单独的结果表中,从而创建1:1的关系。为了保持测试结果的可扩展性,我希望将结果存储在Maps而不是Beans中。
然而,似乎Hibernate不喜欢我的方法。有没有人有这种映射的经验?还有更好的选择吗?
编辑以获取示例和进一步说明
--------
| Test |
|id |
+--------+
|date |
|duration| 1 1 ----------
|... | --------- | Medium |
-------- |testID |
+----------+
|medium |
|pressure |
----------
Medium是测试可以拥有的一个属性。由于可以添加其他属性,我不想对Medium类进行硬编码,而是将其映射为Map,存储三个属性。我的想法是,Test会有Map<String, Map<String, Object>>
来表示与之相关的所有属性。
<?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>
com.hoerbiger.versuchsdb.hibernate.TestAccessor
是一个PropertyAccessor,用于访问我想用于关系的地图
<?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>
为了尝试有效的方法,我使用了这个主要方法。请注意最后几行
@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();
}
这些最后一行有什么用?这是休眠或配置错误的错误吗?
答案 0 :(得分:1)
经过多次阅读后,我找出了我的错误:目前,我的媒体映射看起来像这样:
<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>
但它应该是这样的:
<hibernate-mapping package="com.hoerbiger.versuchsdb.domain">
<class entity-name="Medium" lazy="false">
<id name="id" type="long">
<generator class="foreign">
<param name="property">test</param>
</generator>
</id>
<one-to-one name="test" class="Test" constrained="true"/>
<property name="medium" type="string"/>
<property name="pressure" type="int"/>
</class>
</hibernate-mapping>
问题是在生成器中使用“id”和一对一约束
Hibernate使用两个属性来表示主键一对一约束,在我的例子中:
由于Map不是类型安全的,您可以通过Test覆盖首先存储的Long。两个值都只是读入同一个映射条目。通过将两次出现的id更改为test,引用具有自己的条目,并且不再覆盖id值