2012-02-08 99 views
2

我有一个实体在Oracle模式中持久化。在DB插入中,触发器通过使用DB序列来生成实体ID。使用触发器是强制性的,因为它还更新对于传统组件重要的ID生成序列(日志表类型)旁边的另一个表。Oracle之前插入触发器和Hibernate ID生成器设置

如何在我的实体映射中配置Hibernate ID生成器?

寻找类似的问题#1的时候,我找到了一些解决方案,不适合我的情况:

  1. 直接使用顺序:<generator class="sequence">...</generator>。这是不可能的,因为其余触发代码不会被执行
  2. 使用<generator class="select">...</generator>这意味着在插入后,Hibernate使用另一个唯一属性(根据Hibernate-3.3手册5.1.4.6)选择实体。这在这里也是不可能的,因为没有其他独特的列,并且不支持使用一组属性。
  3. 在拨打save()之前使用<generator class="assigned">...</generator>并设置假ID。此ID将被DB触发器忽略,并且生成的DB行将具有正确的ID。但是,我的Java实例不会有这个解决方案,因为它对触发器的实现做出了假设。

是否有解决此问题的好方法?

+0

什么是标识符?它返回插入的标识号 – Firo 2012-02-08 16:21:18

+1

某些东西听起来如果与该数据库触发器有关,应该只写入一个序列值,如果没有在插入中提供,例如'IF:new .pk_id IS NULL然后选择my_seq.NEXTVAL INTO:new.pk_id FROM DUAL; END IF;' - 然后触发器的其余部分可以使用ID,无论它是由触发器还是由Hibernate提供。 – 2012-02-10 06:32:09

+0

好吧,对不起已经回答了这个问题: @Firo:“身份”不支持Oracle(http://www.roseindia.net/hibernate/hibernateidgenera torelement.shtml) – rainer198 2012-07-09 15:30:22

回答

0

生成ID和更新其他表应该是单独的任务。 您可以直接使用该序列,只在触发器中保留“更新其他表”代码。

为什么不能完成这个任何特定的原因?

+0

至少,必须执行触发器,因为它会更新另一个表(请参阅我今天的评论)。另一方面,我无法更改触发器代码,因为其他应用程序期望触发器正在调用序列。 – rainer198 2012-07-09 15:41:32

+0

您可以将触发器更改为只填充ID,如果它是NULL。然后它也可以被其他应用程序使用。 – jva 2012-07-09 16:09:08

0

<generator class="select">是更正确的解决方案。事实上,你不能选择自动生成的值只是显示了与ypu模型和发电机恕我直言的选择问题。您可以尝试使用<generator class="sequence-identity">,但正如我在javadocs(org.hibernate.id.SequenceIdentityGenerator()中提到的,根据我的经验,对Oracle驱动程序中的getGeneratedKeys的支持很不稳定,或者至少在几年前我第一次开发时并测试该生成器

+0

那么,正如我所描述的,我没有其他独特的列可以用于这个subsequenz选择和组合不支持。 – rainer198 2012-07-09 16:00:07

+0

组合*被*支持。将您想要用作唯一键的属性标记为@NaturalId,并且选择生成器将自动将其用于生成的主键检索。我的观点只是,这也是恕我直言,是一个不好的数据库设置。我的第二点是,你在列表中缺少选项号(4),它将使用' 2012-07-09 18:37:00

+0

@SteveEbersole在Hibernate 3.6.10下,试图使用'select'生成器具有多个标注为“@ NaturalId”的列产生'org.hibernate.id.IdentityGenerationException:select generator当前不支持复合自然标识属性;需要在发电机参数中指定[键]。你能澄清哪个版本的Hibernate支持复合自然键的这个生成器策略吗? – Tim 2015-02-03 16:08:13