如何在本地插入后获取新记录ID

6

出于某些好的原因,我进行了Spring Data JPA本地插入。
查询以正确的方式执行。
但是我需要的是由nextval('hibernate_sequence')生成的新生成的表ID。

有没有办法获取这个ID?

以下是我的查询:

/**
 * Inserts a new file attachment.
 * This is useful and maybe better suitable, because one may not want to load the whole
 * job offer to fullfill the JobOffer -> FileAttachment OneToMany Relation
 *
 * @param file       a given file
 * @param fileName   a given file name
 * @param jobOfferId a given job offer id
 * @return int the new id
 */
@Modifying
@Query(value = "insert into fileattachment(fileattachmentid, file, filename, joboffer_jobofferid) values (nextval('hibernate_sequence'), ?1, ?2, ?3);", nativeQuery = true)
int insertFileAttachment(String file, String fileName, long jobOfferId);

整数返回值仅提供插入记录的数量(1)。但是我需要新的ID。我不想通过另一个数据库查询在插入后查询它。因为如果我必须这样做,整个本地插入就会过时。
有人知道答案/有人有替代方法吗? 谢谢! 问候 Thomas
编辑: 我使用本机插入来避免加载整个工作申请记录,这是很多无用数据中的持久化数据的方式与实体管理器。
相反,我使用本地插入数据。
无论如何,您关于从插入语句返回数据的提示非常酷。 我试了一下,它起作用了。非常感谢您! 我最终采用了这个解决方案:
/**
 * Inserts a new file attachment.
 * This is useful and maybe better suitable, because one may not want to load the whole
 * job offer to fullfill the JobOffer -> FileAttachment OneToMany Relation
 *
 * @param file       a given file
 * @param fileName   a given file name
 * @param jobOfferId a given job offer id
 * @return int the new id
 */
@Query(value = "insert into fileattachment(fileattachmentid, file, filename, joboffer_jobofferid) values (nextval('hibernate_sequence'), ?1, ?2, ?3) returning fileattachmentid;", nativeQuery = true)
long insertFileAttachment(String file, String fileName, long jobOfferId);
3个回答

3
如果您正在使用postgres,则可以简单地执行此操作。关键组件是只需添加RETURNING *,它将返回插入到表中的所有列。然后,您可以简单地添加一个返回类型,该类型将为您映射。此示例是在Kotlin中编写的,也可以轻松适应Java。查询语法是本地的。
@Query(
    """ INSERT INTO table1 (a,b,c)
    select a,b,c from table2 where a = :someNumber
    RETURNING *;
    """, nativeQuery = true
)
fun addToProcessed(finOrVin: String): PojoEntityTest?

References:

https://www.postgresql.org/docs/9.5/sql-insert.html


3

对我来说,只保留@Transactional注释而删除@Modifying注释是有效的。

@Transactional
@Query(value = "my query returning id",nativeQuery = true)
Integer importUserRecord(@Param("login") String user);

在我的服务中,
Integer newId=userRepository.importUserRecord(user);

请注意,如果它是一个对象,我们需要添加 RETURNING *,而只删除 @Modifying 就足够了。 - Kalana Dananjaya

2

有没有一种方法可以获取这个id?

如果不查询数据库,就无法获得。除非你愿意使用纯JDBC。

如果你的FileAttachment有一个@ManyToOne JobOffer offer,那为什么不直接做以下操作:

FileAttachment attachment = new FileAttachment(file, fileName);
attachment.setJobOffer(entityManager.getReference(JobOffer.class, jobOfferId));
entityManager.persist(attachment);
entityManager.flush();
return attachment.getId();

这样做可以避免加载整个 JobOffer 状态。如果关系是单向的,恐怕您将不得不检索整个 JobOffer

或者,如果您确实必须使用本地 INSERT,请考虑在您的数据库中定义一个存储过程来插入数据并返回自动生成的 id(请参见此处)。

此外,一些数据库(例如 PostgreSQL)允许从 INSERT 语句中返回数据(INSERT (..) INTO FILEATTACHMENT RETURNING ID)。您可能需要删除 @Modifying 注释,因为插入的 id 将出现在查询结果集中。您没有提到您使用的是哪种数据库,但语法看起来像 Postgres,这就是我选择这个示例的原因。如果您使用其他数据库,请查阅文档,可能有类似的功能。

然而,我仍然建议不要在 JPA 应用程序中使用本地 INSERT 语句。很多东西都可能会出问题。我怀疑您正在尝试实现的方法不是一个更大的工作单位的一部分,但如果是这种情况,我会非常小心。


只是好奇... entityManager.getReference(JobOffer.class, jobOfferId) 在客户端/服务器环境中能用吗? - Thomas Lang
你是什么意思? - crizzis
抱歉crizzis,我对getReference有些误解。请不要再介意我的问题了。非常感谢您的有用帮助!敬礼-Thomas。 - Thomas Lang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接