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

Spring Data JDBC操作SQL Server保存实体后UUID ID为空问题

问题:Spring Data JDBC操作SQL Server 2019时UUID主键保存报错

数据库表定义

create table users
(
    user_id uniqueidentifier default newid() not null primary key,
    name    varchar(192),
    ...
)

实体类代码

import org.springframework.data.annotation.Id;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import java.util.UUID;

@Table(value = "users")
public class User {
   
    @Id
    @Column("user_id")
    private UUID userId;

    // 省略getter/setter及其他字段
}

报错信息

使用H2模拟SQL Server环境时save操作正常,但在真实SQL Server 2019中调用CrudRepository<User, UUID>.save()时触发以下错误:

java.lang.IllegalArgumentException: After saving the identifier must not be null!
    at org.springframework.util.Assert.notNull(Assert.java:201)
    at org.springframework.data.jdbc.core.JdbcAggregateTemplate.store(JdbcAggregateTemplate.java:364)
    at org.springframework.data.jdbc.core.JdbcAggregateTemplate.save(JdbcAggregateTemplate.java:161)

当前临时方案

通过BeforeConvertCallback在客户端生成UUID实现功能,但并非理想方案:

@Bean
BeforeConvertCallback<User> beforeConvertCallback() {
    return (user) -> {
        if (user.getUserId() == null) {
            user.setUserId(UUID.randomUUID());
        }
        return user;
    };
}

问题核心:Spring Data JDBC期望从GENERATED_KEYS结果集获取生成的ID,但SQL Server未正确返回该值,导致断言失败。


解决方案(仅基于Spring Data JDBC)

1. 调整实体类ID注解配置

Spring Data JDBC 2.4+版本针对SQL Server UUID主键生成提供了专属策略,修改实体类ID字段的注解:

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.GeneratedValue;
import org.springframework.data.annotation.GenerationType;
import org.springframework.data.relational.core.mapping.Column;
import org.springframework.data.relational.core.mapping.Table;
import org.springframework.data.jdbc.core.mapping.SqlServerUuidGenerationStrategy;
import java.util.UUID;

@Table(value = "users")
public class User {
   
    @Id
    @Column("user_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = SqlServerUuidGenerationStrategy.NAME)
    private UUID userId;

    // 省略getter/setter及其他字段
}

2. 确保依赖版本适配

  • 使用Spring Data JDBC 2.4.x及以上版本:该版本开始原生支持SQL Server的UUID主键返回逻辑,会自动使用SQL Server的OUTPUT子句替代标准的RETURNING来获取生成的ID
  • 使用Microsoft SQL Server JDBC驱动9.4及以上版本:旧版本驱动对UUID生成键的返回存在兼容性问题

3. 验证数据库主键策略

确保数据库表的user_id字段确实配置了default newid(),若后续需要更有序的UUID,可改为default newsequentialid(),实体类注解无需额外修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 16:05:08