JPA如何正确映射SQL Server带NEWID()默认值的UNIQUEIDENTIFIER主键
问题根因
你遇到的两个问题本质原因分别是:
- 默认配置下Hibernate会将
java.util.UUID序列化为二进制数组传入SQL Server,Java的UUID采用大端字节序,而SQL ServerUNIQUEIDENTIFIER类型的前三个字段采用小端字节序,直接存二进制会导致字节序翻转,出现实体值和数据库存储值不一致的情况 - 原生
GenerationType.IDENTITY策略Hibernate默认没有适配UUID类型的主键返回逻辑,所以会抛出类型不匹配的异常
方案1:Hibernate生成UUID,与数据库存储值完全一致
该方案不需要依赖数据库的NEWID()默认值,直接让Hibernate生成UUID并正确写入数据库,实体id值和数据库存储值100%匹配,是最常用的解决方案:
@Entity @Table(name = "some_table") public class MyEntity { @Id @Column(columnDefinition = "uniqueidentifier", nullable = false) @GeneratedValue(generator = "uuid2") @GenericGenerator(name = "uuid2", strategy = "org.hibernate.id.UUIDGenerator") // *核心配置*:指定Hibernate将UUID转为字符串和数据库交互,避免字节序翻转问题 @Type(type = "org.hibernate.type.UUIDCharType") private UUID id; // 其他字段、getter、setter }
直接调用repository.save(entity)即可,无需手动设置id,保存后返回的实体id和数据库存储值完全一致。
方案2:使用数据库侧NEWID()生成主键,插入后回写实体
如果必须由数据库生成主键,使用如下配置即可,插入后数据库生成的UUID会自动回写到实体对象:
@Entity @Table(name = "some_table") public class MyEntity { @Id @Column(columnDefinition = "uniqueidentifier", nullable = false, insertable = false, updatable = false) // 标注该字段值由数据库插入时生成,插入后Hibernate会自动回查回填 @Generated(GenerationTime.INSERT) @Type(type = "org.hibernate.type.UUIDCharType") private UUID id; // 其他字段、getter、setter }
注意事项:
- 不需要添加
@GeneratedValue注解,避免触发Hibernate的id生成逻辑 insertable = false表示插入SQL时不携带id字段,让数据库触发NEWID()默认值逻辑- 确保使用4.0及以上版本的
mssql-jdbc驱动,支持返回生成的UNIQUEIDENTIFIER类型主键
内容的提问来源于stack exchange,提问作者Ralf
相关产品推荐
相关产品推荐

