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
相关产品推荐
相关产品推荐

