hibernate 默认的命名策略是不会将驼峰式命名 (cameCase
) 映射到蛇形命名 (snake_case
) 上去的,
虽然可以直接在 @Column
上指定需要映射的 name
,但是使用策略一致地应用命名更方便些。
从 Hibernate 5 开始,数据库对象命名策略由 PhysicalNamingStrategy
接口表示,我们可以自定义该接口以自动将数据库标识符从 cameCase 转换为 snake_case。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
| 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
,则不需要该自定义策略:
1 2 3 4 5
| <dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>${hibernate-types.version}</version> </dependency>
|
要使用自定义的策略类,只需要将该类配置给 hibernate.physical_naming_strategy
属性:
1 2 3
| <property name="hibernate.physical_naming_strategy" value="com.vladmihalcea.hibernate.type.util.CamelCaseToSnakeCaseNamingStrategy" />
|
在 Spring Data JPA 中该策略的默认配置为:
org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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