【问题标题】:How to get new record ID after native insert本机插入后如何获取新记录ID
【发布时间】:2018-10-08 01:14:49
【问题描述】:

出于一些很好的原因,我做了一个 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);

int 返回值只是给出插入记录的数量(1)。
但我需要新的身份证。
我不想在插入另一个数据库查询后查询它。因为如果我必须这样做,整个原生插入就会过时。

有人知道答案/有其他提示吗?
谢谢!
亲切的问候
托马斯

编辑
我使用原生插入避免加载整个joboffer记录,这是很多无用的数据,只是为了将数据以entitymanager的方式持久化。

相反,我插入本地数据。

无论如何,从插入语句返回数据的提示非常酷。
我正在尝试,它正在工作。非常感谢!
我最终得到了这个解决方案:

/**
 * 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);

【问题讨论】:

    标签: hibernate jpa spring-data-jpa


    【解决方案1】:

    有没有办法得到这个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(请参阅 here)。

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

    但是,我仍然建议不要在 JPA 应用程序中使用本机 INSERT 语句。很多东西都会坏掉。我怀疑您尝试实施的方法不是更大工作单元的一部分,但如果是这种情况,我会非常小心。

    【讨论】:

    • 只是好奇...... entityManager.getReference(JobOffer.class, jobOfferId) 在客户端/服务器环境中是否有效?
    • 你是什么意思?
    • 对不起 crizzis,我误解了一些关于 getReference 的内容。请不要再介意我的问题了。感谢您的有用帮助!亲切的问候 - 托马斯。
    【解决方案2】:

    如果您使用的是 postgres,您可以简单地执行此操作。关键组件只是添加一个RETURNING *,它将返回插入到表中的所有列。然后,您可以简单地添加一个将为您映射的返回类型。这是在 Kotlin 中,也可以很容易地适应 java。 Query 语法是原生的。

    @Query(
        """ INSERT INTO table1 (a,b,c)
        select a,b,c from table2 where a = :someNumber
        RETURNING *;
        """, nativeQuery = true
    )
    fun addToProcessed(finOrVin: String): PojoEntityTest?
    

    参考资料:

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

    【讨论】:

      【解决方案3】:

      删除 @Modifying 注释并仅保留 @Transactional 对我有用

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

      为我服务

      Integer newId=userRepository.importUserRecord(user);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-06
        • 2017-02-15
        • 1970-01-01
        相关资源
        最近更新 更多