You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA执行原生INSERT查询后如何获取插入的实体及对应ID

问题原因

Spring Data JPA 中被@Modifying标记的写操作查询(INSERT/UPDATE/DELETE),默认仅支持void、int/Integer(返回受影响行数)、boolean/Boolean(返回是否有行被修改)三类返回值,不支持直接返回实体类,这是你遇到报错的根本原因。


解决方案

你可以根据自己的技术栈选择以下任意一种方案解决:

方案1:拆分插入+查询操作(全数据库兼容)

这个方案不需要修改SQL语法,兼容性最强。

  1. 调整Repository方法的返回值为int:
@Query(value = INSERT_USER_IN_TO_DATABASE, nativeQuery = true)
@Modifying
int saveNewUser(String encryptionKey,
             String phoneNumber,
             String name,
             String lastName,
             String gender,
             String dob);
  1. 在业务逻辑层先执行插入方法,判断返回值为1说明插入成功,再通过业务唯一键(比如手机号、用户ID等)查询刚插入的实体即可。注意需要在业务方法上加@Transactional注解,保证插入和查询操作的原子性。

方案2:用数据库RETURNING语法直接返回插入结果(适配支持该语法的数据库)

如果你的数据库是PostgreSQL、MySQL 8.0+、Oracle、SQL Server等支持插入后返回行的数据库,可以直接修改SQL拿到返回实体:

  1. 调整原生SQL,在末尾加上对应数据库的返回行语法,示例(不同数据库语法略有差异,按需调整):
// 示例为SQL Server语法,用OUTPUT返回插入行;PostgreSQL/MySQL 8.0+直接写RETURNING *即可
String INSERT_USER_IN_TO_DATABASE = "INSERT INTO USER_MASTER " +
        "(" +
        "MOBILE_X,USER_TYPE,COUNTRYCODE,USER_N,USER_LAST_N,GENDER,DOB) " +
        "VALUES ( " +
        "EncryptByKey(Key_GUID(convert(varchar,?1)), ?2)," +
        "1,+91,?3,?4,?5,?6" +
        ")" +
        "OUTPUT inserted.*";
  1. 移除方法上的@Modifying注解,返回值保留UserMasterEntity即可,Spring Data JPA会自动将返回的行映射为实体对象。

方案3:用@ColumnTransformer实现自动加解密,复用JPA原生save方法

你之前尝试的@ColumnTransformer本身是可行的,只是需要调整使用方式,不需要自己写原生INSERT:

  1. 在UserMasterEntity的手机号字段上配置加解密规则:
@Column(name = "MOBILE_X")
@ColumnTransformer(
    write = "EncryptByKey(Key_GUID(convert(varchar, ?1)), ?2)",
    read = "DecryptByKey(MOBILE_X)"
)
private String mobileX;
  1. 实体中其他固定字段(USER_TYPE、COUNTRYCODE)可以直接设置默认值,构造实体时赋值即可。
  2. 直接调用JPA Repository自带的save()方法插入实体,插入完成后会自动返回带主键的完整实体,不需要自定义插入语句。注意使用该方案需要保证操作前已经打开了对应的数据库加密密钥。

内容的提问来源于stack exchange,提问作者Arun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 21:24:01