如果触发器生成值,如何注释Id列?

Zee*_*mee 8 oracle hibernate jpa

我有一个使用Oracle XE 10g,Hibernate 3.5,JPA 2.0的设置.有一个带主键的简单表,它由插入时的数据库触发器生成.触发器从序列中获取值.触发器/序列构造由Oracle XE完成.

实际问题是:如何在EntityManager.persist之后获取我的实体中Id的当前值?
我试过了:

@Id
private long id;
Run Code Online (Sandbox Code Playgroud)

- > id是0;

@Id
@Generated(GenerationTime.ALWAYS)
@Column(insertable = false, updatable = false)
private long id;
Run Code Online (Sandbox Code Playgroud)

- > id是0;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private long id;
Run Code Online (Sandbox Code Playgroud)

- >失败,因为Hibernate试图直接查询序列(不存在).

前两种方法在数据库中生成ID,但我的对象中没有值.

Chr*_*ang 7

与@JB Nizet的评论相反,我实际上可以想到为什么我们让触发器分配ID的许多原因:执行存储过程,手动执行SQL和在Hibernate中运行本机查询,仅举几例.

我个人发现以下解决方案相当令人满意.它允许Hibernate找到最大ID,并在每次调用insert语句时使其递增.但是当语句命中数据库时,ID将被忽略并被触发器生成的ID覆盖,因此群集问题中没有唯一性:

    @Id
    @GeneratedValue(generator="increment")
    @GenericGenerator(name="increment", strategy = "increment")
    private Long id;
Run Code Online (Sandbox Code Playgroud)

最大的缺点是@GenericGenerator是一个Hibernate注释,因此你失去了JPA的可移植性.程序员也不清楚这个ID实际上是否与序列相关联.

另一种方法是修改触发器,使其仅在ID为null时递增序列.请参阅" Oracle Trigger的Hibernate问题,用于从序列生成id ".在大多数情况下,这是最好的解决方案,因为它清楚地显示ID与序列相关联.我唯一的抱怨是它为user/hibernate提供了插入任何ID的选项,而不是首先实际查询序列.


atr*_*ain 2

除非您绑定到触发器,否则这似乎是对序列的一定程度的混淆,并且似乎超出了正常的 Hibernate 生命周期。为什么不直接调用序列:

@SequenceGenerator(name="alias_for_my_sequence", sequenceName="seq_name_in_oracle")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="alias_for_my_sequence")
@Id
private Long id;
Run Code Online (Sandbox Code Playgroud)

然后您将获得该值,因为 Hibernate 直接参与生成,并且事后不会发生任何事情。

  • @Mulmoth:除非有另一个字段唯一标识该行,否则Hibernate将如何从数据库中获取生成的ID,因为标识刚刚插入的行的唯一方法是它的ID,它不知道。总之,需要ID才能拿到ID。你的触发器是一个非常糟糕的主意。 (2认同)