Java JPA(EclipseLink)如何在持久化实际实体之前接收下一个 GeneratedValue?

Posted

技术标签:

【中文标题】Java JPA(EclipseLink)如何在持久化实际实体之前接收下一个 GeneratedValue?【英文标题】:Java JPA (EclipseLink) How to receive the next GeneratedValue before persisting actual entity? 【发布时间】:2011-09-30 08:11:12 【问题描述】:

我正在使用 JPA 的 EclipseLink 实现,但遇到了问题。

这是我的实体类:

@实体 @Table(name = "出席人数") 公共类出勤实现可序列化 私有静态最终长序列版本UID = 1L; @ID @GeneratedValue(策略 = GenerationType.IDENTITY) @基本(可选=假) @Column(name = "id") 私人短 id; ....

在我的 mysql 表(即底层数据存储)中,我还设置了 auto_increment 标志。

如何在持久化实体之前获取自动生成的值(id 字段)? 所以如果表中有 3 个实体(id IN (1, 2, 3)),我想获取 4 个作为下一个自动生成的值。

我唯一的解决方法是:

    获取id字段最大的实体的id。

我能做的就这么多吗?

【问题讨论】:

你为什么要这样做? @Nizet 我有一个用于创建出勤的对话框,我希望用户知道即将创建的出勤的 ID。据说这不是 100% 需要的。 @JB Nizet:确实是一个非常有效的问题。 【参考方案1】:

如果使用 JPA 2.0,您可以试试这个,

entityManagerFactory.getPersistenceUnitUtil().getIdentifier(attendance);

免责声明: 自己从未尝试过。

否则,您可以将您的 id 生成策略更改为可以在持久化实体之前获得id 的东西。例如,尝试使用表生成器来生成您的ids。在这里,我找到了一个例子,Use Table Generator To Generate ID。然后,您将能够直接从该表中读取值。您可能无法使用@Id 自动处理此问题,确切地说,您最终将自己计算下一个id。因此,您可以采用相同的想法,但自己完成所有工作并在创建操作时设置id,并且不要让 JPA 生成一个。

或者,如果支持,您可能想使用sequence。在sequence 的情况下,您还需要自己获取下一个值并手动设置。准备好在没有插入的情况下放弃跳过的ids,或者以某种方式处理。

或者你对你正在做的事情很好。只需注意原子性。或者您可能不会遇到多个事务同时运行的情况。

【讨论】:

getIdentifier 调用不起作用。该方法的文档说:“返回实体的 id。在数据库插入发生之前,生成的 id 不能保证可用。如果实体还没有 id,则返回 null。” @JB Nizet:那么我应该使用表格生成器吗? @JB Nizet:是的,我也不能保证。我的意思是,正如我所说,我从未尝试过。顺便说一句,不能保证也可以推断它可能有效。无论如何,我也给出了第二个建议,OP可能会考虑。 @Daniel:是的,无论如何。但是尝试一次不会有任何伤害。很简单,你看。 @Daniel:不。 TableGenerator 在持久化之前不会让您知道 ID,因为它是持久化调用生成器来获取 ID。您必须自己分配 ID。

以上是关于Java JPA(EclipseLink)如何在持久化实际实体之前接收下一个 GeneratedValue?的主要内容,如果未能解决你的问题,请参考以下文章

JPA + EclipseLink+ HSQLDB 不创建表

JPA 使用指南 /Eclipselink/JPA 实体生成器

JPA + EclipseLink + SAP云平台 = 运行在云端的数据库应用

JPA + EclipseLink + SAP云平台 = 运行在云端的数据库应用

使用 EclipseLink JPA 将 XML 类型存储到 PostgreSQL

JPA/EclipseLink - 计算列