hibernate 默认的命名策略是不会将驼峰式命名 (cameCase
) 映射到蛇形命名 (snake_case
) 上去的,
虽然可以直接在 @Column
上指定需要映射的 name
,但是使用策略一致地应用命名更方便些。
从 Hibernate 5 开始,数据库对象命名策略由 PhysicalNamingStrategy
接口表示,我们可以自定义该接口以自动将数据库标识符从 cameCase 转换为 snake_case。
public class CamelCaseToSnakeCaseNamingStrategy
extends PhysicalNamingStrategyStandardImpl {
public static final CamelCaseToSnakeCaseNamingStrategy INSTANCE =
new CamelCaseToSnakeCaseNamingStrategy();
public static final String CAMEL_CASE_REGEX = "([a-z]+)([A-Z]+)";
public static final String SNAKE_CASE_PATTERN = "$1\\_$2";
@Override
public Identifier toPhysicalCatalogName(
Identifier name,
JdbcEnvironment context) {
return formatIdentifier(
super.toPhysicalCatalogName(name, context)
);
}
@Override
public Identifier toPhysicalSchemaName(
Identifier name,
JdbcEnvironment context) {
return formatIdentifier(
super.toPhysicalSchemaName(name, context)
);
}
@Override
public Identifier toPhysicalTableName(
Identifier name,
JdbcEnvironment context) {
return formatIdentifier(
super.toPhysicalTableName(name, context)
);
}
@Override
public Identifier toPhysicalSequenceName(
Identifier name,
JdbcEnvironment context) {
return formatIdentifier(
super.toPhysicalSequenceName(name, context)
);
}
@Override
public Identifier toPhysicalColumnName(
Identifier name,
JdbcEnvironment context) {
return formatIdentifier(
super.toPhysicalColumnName(name, context)
);
}
private Identifier formatIdentifier(
Identifier identifier) {
if (identifier != null) {
String name = identifier.getText();
String formattedName = name
.replaceAll(
CAMEL_CASE_REGEX,
SNAKE_CASE_PATTERN)
.toLowerCase();
return !formattedName.equals(name) ?
Identifier.toIdentifier(
formattedName,
identifier.isQuoted()
) :
identifier;
} else {
return null;
}
}
}
如果你引用了 hibernate-types
,则不需要该自定义策略:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
要使用自定义的策略类,只需要将该类配置给 hibernate.physical_naming_strategy
属性:
<property name="hibernate.physical_naming_strategy"
value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy"
/>
在 Spring Data JPA 中该策略的默认配置为:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
实现如下:
// 是否驼峰,根据 aBa 类型判断
private boolean isUnderscoreRequired(char before, char current, char after) {
return Character.isLowerCase(before) && Character.isUpperCase(current)
&& Character.isLowerCase(after);
}
private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
if (name == null) {
return null;
}
StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
for (int i = 1; i < builder.length() - 1; i++) {
if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i),
builder.charAt(i + 1))) {
builder.insert(i++, '_');
}
}
return getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
}
隐式命名策略 (ImplicitNamingStrategy
) 在缺省时提供相应的命名处理:
- 实体主表:
@Table
- 连表:
@JoinTable
- 集合表:
@CollectionTable
- 列命名:
@Column
Spring Data JPA 模式隐式命名策略为:
org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy