如何在Hibernate 6与Spring Boot 3中正确配置数据库级默认值
为SQL Server字段设置Hibernate默认值的正确方式
问题场景
在Hibernate 6之前,Hibernate不会触发修改数据库或字段长度的ALTER语句,但通过columnDefinition设置default关键字时,生成的ALTER语句在SQL Server中语法无效。
代码片段
public abstract class AbstractAuditingEntity implements Serializable { private static final long serialVersionUID = 8559071964734620120L; @CreatedBy @JsonIgnore @Column(name = "CREATED_BY", updatable = false) private Integer createdBy; @CreatedDate @JsonIgnore @Column(name = "CREATED_DATE", columnDefinition="datetime default GETDATE()", updatable = false) private Instant createdDate = Instant.now(); @LastModifiedBy @JsonIgnore @Column(name = "LAST_MODIFIED_BY") private Integer lastModifiedBy; @LastModifiedDate @JsonIgnore @Column(name = "LAST_MODIFIED_DATE") private Instant lastModifiedDate = Instant.now(); }
Hibernate生成的错误DDL语句
alter table TABLE_NAME alter column CREATED_DATE datetime default GETDATE()
抛出的异常
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table TABLE_NAME alter column CREATED_DATE datetime default GETDATE()" via JDBC [Incorrect syntax near the keyword 'default'.]
SQL Server中默认值属于约束,需要使用ADD CONSTRAINT语法,但可以通过Hibernate的特定方式实现正确的默认值配置。
正确实现方式
方法1:使用Hibernate扩展注解@ColumnDefault
Hibernate提供了org.hibernate.annotations.ColumnDefault注解,专门用于配置数据库字段的默认值,它会根据数据库方言自动生成符合语法的DDL语句,避免手动写columnDefinition带来的语法问题。
修改后的代码示例:
import org.hibernate.annotations.ColumnDefault; public abstract class AbstractAuditingEntity implements Serializable { private static final long serialVersionUID = 8559071964734620120L; @CreatedBy @JsonIgnore @Column(name = "CREATED_BY", updatable = false) private Integer createdBy; @CreatedDate @JsonIgnore @Column(name = "CREATED_DATE", updatable = false) @ColumnDefault("GETDATE()") private Instant createdDate = Instant.now(); @LastModifiedBy @JsonIgnore @Column(name = "LAST_MODIFIED_BY") private Integer lastModifiedBy; @LastModifiedDate @JsonIgnore @Column(name = "LAST_MODIFIED_DATE") @ColumnDefault("GETDATE()") private Instant lastModifiedDate = Instant.now(); }
方法2:自定义columnDefinition(需遵循SQL Server约束语法)
如果需要同时配置字段的其他属性,可以手动在columnDefinition中指定完整的约束定义,但这种方式在生成ALTER语句时可能存在兼容性问题,仅推荐在创建表时使用:
@Column(name = "CREATED_DATE", columnDefinition="datetime CONSTRAINT DF_CREATED_DATE DEFAULT GETDATE()", updatable = false)
额外注意事项
- 实体类中
= Instant.now()是Java对象初始化时的默认值,和数据库层面的默认值相互独立。如果希望数据库自动使用默认值,可在类级别添加@DynamicInsert注解,这样当字段为null时,Hibernate生成的INSERT语句不会包含该字段,数据库会自动应用默认值。 - 确保Hibernate配置了正确的SQL Server方言,比如
org.hibernate.dialect.SQLServerDialect或对应版本的方言,以保证生成的DDL适配SQL Server语法。
内容的提问来源于stack exchange,提问作者aakash singh
相关产品推荐
相关产品推荐

