我们正在使用一个遗留数据库,我想知道我们的设置是否完全可以使用 Hibernate 的方式:
我们有两个表 Entity 和 EntityDef
CREATE TABLE entity
(
id DOUBLE,
name VARCHAR(20),
PRIMARY KEY (id)
)
CREATE TABLE entitydef
(
id DOUBLE,
effectivedate DATE,
terminationdate DATE,
category VARCHAR(20),
PRIMARY KEY (id, terminationdate)
)
基本上,对于每个实体,它可以有多个相应的 EntityDef,它们指定特定有效期的参数。这些 EntityDef 的有效期是不相交的,因此在任何给定时间,Entity 和 EntityDef 之间应该存在一对一的关系。当尝试使用休眠来映射实体表时,问题就出现了。我们使用以下映射
<class name="com.company.Entity" table="Entity">
<cache usage="read-write" />
<id name="id" type="long">
<column name="id" />
</id>
<property name="name" type="string">
<column name="name" />
</property>
<join table="entitydef">
<key>
<column name="id" sql-type="long />
</key>
<property name="category" type="string">
<column name="category" />
</property>
</join>
</class>
<class name="com.company.EntityDef" table="entitydef">
<cache usage="read-write" />
<composite-id>
<key-property name="id" type="long">
<column name="id" />
</key-property>
<key-property name="terminationDate" type="com.company.time.hibernate.Date">
<column name="terminationdate" />
</key-property>
</composite-id>
<property name="category">
<column name="category" />
</property>
</class>
当不同的休眠映射仅通过其 ID 引用具有多个 EntityDef 的实体时,就会出现问题。
...
<many-to-one name="entity" class="com.company.Entity" lazy="false">
<column name="entityid" />
</many-to-one>
...
Hibernate 通过其 ID 查询实体并抛出一个有意义的异常:
org.hibernate.HibernateException: More than one row with the given identifier was found: 1, for class: com.company.Entity
我们尝试向 EntityDef 映射添加过滤器,如 Hibernate 文档中所示:
<filter-def name="effectiveDate">
<filter-param name="asOfDate" type="date" />
</filter-def>
<class name="com.company.EntityDef" table="entitydef">
<cache usage="read-write" />
<composite-id>
<key-property name="id" type="long">
<column name="id" />
</key-property>
<key-property name="terminationDate" type="com.company.time.hibernate.Date">
<column name="terminationdate" />
</key-property>
</composite-id>
<property name="category">
<column name="category" />
</property>
<filter name="effectiveDate" condition=":asOfDate BETWEEN effectivedate and terminationdate" />
</class>
并将以下代码添加到我们的查询中:
sess.enableFilter("effectiveDate").setParameter("asOfDate", new Date());
但这似乎并没有影响任何事情。
我的问题是:这种设置是否可行,有没有办法在不明确指定终止日期的情况下加入 EntityDef 表?如果不是,最好的解决方案是什么?创建一对多关系并使用 Entity 类中的逻辑从集合中获取正确的 EntityDef?
有很多业务逻辑期望类别等成为实体的一部分,因此如果我们不必诉诸一对多关系,那将是非常好的。
谢谢!