我想知道是否有办法对以下内容进行Hibernate映射。我花了两天时间就说没有。
有两个表,one to many
关系。
+---------------------+ +-----------------+
| versioned_entity | | basic_entity |
+---------------------+ +-----------------+
| fk_BasicEntityId | * 1 | id |
| version |-------| active_version |
| ... | | ... |
+---------------------+ +-----------------+
Hibernate映射:
<class name="my.VersionedEntity" table="versioned_entity">
<composite-id>
<key-many-to-one name="basicEntity" column="fk_BasicEntityId"/>
<key-property name="version"/>
</composite-id>
...
</class>
<class name="my.BasicEntity" table="basic_entity">
<id name="id">
<property name="activeVersion" not-null="true">
<column name="active_version"/>
</property>
...
</class>
简要说明:fk_BasicEntityId
是指向basic_entity.id
的外键。 versioned_entity
中的条目可以通过其外键和version
来标识(可以有许多版本具有相同的fk_BasicEntityId
)。 active_version
是一个指向versioned_entity
个条目之一的数字,它告诉哪个版本是“活动的”。希望这很清楚。
现在我要解决的问题是我需要像Java这样快速访问Java:
my.BasicEntity basic = my.BasicEntityDAO.get();
my.VersionedEntity activeVersion = basic.getActiveVersionedEntity();
当前实现是在Java中完成的,只是迭代给定基本实体的所有版本化实体,并检查其版本是否与活动版本匹配。毋庸置疑,这不会扩展并导致性能问题。
所以我继续把它移到数据库级别。看起来容易?所以我认为!我接着将其添加到basic_entity的Hibernate映射中:
<many-to-one name="activeVersionedEntity" not-null="false" insert="false" update="false">
<column name="id" unique="true" not-null="true"/>
<column name="activeVersion"/>
</many-to-one>
此处需要双列,versioned_entity
具有复合键。
不幸的是,这不起作用 - 当调用be.getActiveVersionedEntity()
时,JVM会在没有跟踪的情况下死掉(在同事的机器上它会在Hibernate中抛出StackOverflowError)。我怀疑这是因为“id”也是一个标识符,因为我对同一个类的映射非常相似,其中列不是标识符,这可以正常工作。
我可以用HQL做到这一点,但这需要我将这个方法移到DAO类中,这特别笨拙,因为需要更改API(不是选项)。在my.BasicEntity::getActiveVersionedEntity()
中使用DAO调用是另一个重要的禁忌:我不能混淆不同的抽象层。解决这个问题的另一种方法是调查拦截器/事件,但是这也可能是那些超出框架目的的选项之一(我不应该关心像这样的低级别事情,是吗?)。
我正在运行Hibernate版本:3.2.7GA / Spring 2.5.6。文档令人难以置信 - 我已经查看了三本不同的Hibernate书籍,在线文档,论坛等。
感谢任何帮助。
答案 0 :(得分:1)
为什么将active_version映射为属性?我怀疑它是一个整数,对吧?为什么不将active_version更改为VersionedEntity类型?这样,这将是一个简单的一对一关系。
更新
我们正在为我们的某个网站使用此映射:
<many-to-one class="my.VersionedEntity" name="currentVersion" lazy="false" />
答案 1 :(得分:0)
听起来你正试图对某一列进行双重映射。我没有详细了解您的问题,但您是否考虑在其中一个映射上使用update = false和insert = false?这应该使您能够将同一列的双重映射作为关系和整数。更多信息here。
答案 2 :(得分:0)
您是在建模双向引用关系还是继承层次结构?
如果对象模型是继承层次结构,则关系不应该是双向的,解决方案是从子类DAO获取子类实例。这消除了从基类导航到基类DAO中的子类的需要。这是我在原来的答案(下面)中试图解释的。
如果对象模型是双向关系,那么你需要在关系的“一”端的集合或包上设置inverse =“true” - 在本例中为BasicEntity。
Hibernate 3允许在关系的“一”端使用索引集合,但是带有set或bag的Hibernate 2功能应该足以测试理论。
此链接可能有所帮助:https://www.hibernate.org/193.html 另外:Hibernate Quickly pp142 - 145; Hibernate in Action pp108 - 111。
如果我正确理解了这个问题,你想从两个表中构建一个VersionedEntity,使用如下获得的数据:
select * from basic_entity be, versioned_entity ve where ve.id = be.id and ve.id = <id> and ve.active_version=<version>
鉴于你没有从另一个调用一个DAO的限制,我想知道所选方法是否正确表达了意图:
public my.VersionedEntity my.BasicEntityDAO.getActiveVersionedEntity();
你能否实现这样的方法:
public my.VersionedEntity my.VersionedEntityDAO.getActive();