Spring Boot 2.0.0.RELEASE项目建表时@Column(unique=true)约束名大小写警告问题
我之前也碰到过一模一样的问题!这个警告(SQL Warning Code: 0, SQLState: 00000)其实是Hibernate自动生成的唯一约束名和数据库实际存储的名称大小写不匹配导致的——你看到的UK_qhp5om4s0bcb6j0j8pgcwitke是Hibernate生成的首字母大写版本,但数据库自动把它转成了小写的uk_qhp5om4s0bcb6j0j8pgcwitke,当Hibernate后续检查约束时就会因为名称对不上抛出警告,根源就在你用的@Column(unique = true)注解上。
为什么会出现这个问题?
- Spring Boot 2.0.0.RELEASE默认搭配的是Hibernate 5.2.x版本,这个版本的Hibernate在自动生成约束名时,默认会用首字母大写的格式。
- 不少数据库(比如PostgreSQL、开启了特定配置的MySQL)会自动把所有标识符(包括约束名、表名)转为小写存储,这就造成了Hibernate生成的名称和数据库实际存的名称不一致,触发了那个看似无厘头的警告。
几个可行的解决办法
1. 让Hibernate统一生成小写的约束名(全局配置)
最省心的方式是修改Hibernate的命名策略,强制它生成小写的标识符。在你的application.properties里加这两行:
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
如果上面的默认策略没生效,你可以自定义一个物理命名策略类,彻底强制所有标识符小写:
import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; public class LowerCasePhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl { @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) { return Identifier.toIdentifier(name.getText().toLowerCase(), name.isQuoted()); } @Override public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) { return Identifier.toIdentifier(name.getText().toLowerCase(), name.isQuoted()); } @Override public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) { return Identifier.toIdentifier(name.getText().toLowerCase(), name.isQuoted()); } @Override public Identifier toPhysicalConstraintName(Identifier name, JdbcEnvironment context) { return Identifier.toIdentifier(name.getText().toLowerCase(), name.isQuoted()); } }
然后在配置文件里指定这个自定义策略:
spring.jpa.hibernate.naming.physical-strategy=com.yourproject.package.LowerCasePhysicalNamingStrategy
把com.yourproject.package换成你实际的包路径就行。
2. 手动指定约束名(局部解决)
如果你不想改全局配置,也可以直接在@Column注解里手动指定唯一约束的名称,确保和数据库存储的大小写一致:
@Column(unique = true, uniqueConstraints = @UniqueConstraint(name = "uk_qhp5om4s0bcb6j0j8pgcwitke")) private String yourColumnName;
直接用数据库里实际存在的小写约束名,Hibernate就不会因为找不到匹配的约束而警告了。
3. 调整数据库的标识符大小写配置(谨慎操作)
比如MySQL里的lower_case_table_names参数,设置为1时会自动把所有标识符转小写。不过修改数据库配置可能影响其他应用,除非你能确定整个环境都用小写标识符,否则不推荐这种方式。
最后说两句
这个警告本身不会影响应用功能,但看着日志里的WARN总归不舒服。我个人更推荐第一种全局配置的方式,一劳永逸解决所有标识符大小写不匹配的问题。
内容的提问来源于stack exchange,提问作者lealceldeiro

