本次示例的项目中,定义了如下两个实体:
@Data
@Entity
public class Teacher {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "Name")
private String name;
}
@Data
@Entity
@Table(name = "teacher_class")
public class TeacherClass {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private Integer teacherId;
@Column(name = "ClassName")
private String className;
}
先来看看 JPA 默认的命名策略,我们可以显示配置如下:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
hibernate:
ddl-auto: create
naming:
# 1. 表名及字段全小写下划线分隔命名策略(默认)
physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy
Hibernate: create table teacher (id integer not null auto_increment, name varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table teacher_class (id integer not null auto_increment, class_name varchar(255), teacher_id integer, primary key (id)) engine=InnoDB
运行项目,通过数据库或输出的SQL语句,默认策略的表现为:表名及字段全小写,并以下划线分隔
此外,引入的 Hibernate 还提供了另外一种物理命名策略,先进行如下配置,再来观察结果:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
hibernate:
ddl-auto: create
naming:
# 2. 物理命名策略,未定义 @Table 和 @Column 将以实体名和属性名作为表名及字段名
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
Hibernate: create table Teacher (id integer not null auto_increment, Name varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table teacher_class (id integer not null auto_increment, ClassName varchar(255), teacherId integer, primary key (id)) engine=InnoDB
以上表明,Hibernate 提供的命名策略是以实体名和属性名分别作为表名及字段名,但如果有定义 @Table
和 @Column
,则以该属性值进行映射命名
当然,某些场景下,可以通过自定义命名策略来简化操作,或实现自身特定的业务,例如:假设需要为未定义 @Table
实体加上表前缀 tb_
,或是以大写字母下划线来分隔定义字段(简单起见,以下配置并不直接实现 PhysicalNamingStrategy
):
public class CustomNamingStrategyConfig extends SpringPhysicalNamingStrategy {
/**
* 配置映射的数据表名
*
* @param name
* @param jdbcEnvironment
* @return
*/
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
if (name == null) {
return null;
}
// 实体名 or 自定义的@Tabel name属性值
String text = name.getText();
// 首字母大写(类名),实体未定义@Table, 为表名加上tb_前缀
if (Character.isUpperCase(text.charAt(0))) {
final String tb = "tb_";
if (!text.contains(tb)) {
text = "tb" + text;
}
StringBuilder builder = new StringBuilder(text.replace('.', '_'));
for (int i = 1, maxLength = builder.length() - 1; i < maxLength; i++) {
if (this.isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i), builder.charAt(i + 1))) {
builder.insert(i++, '_');
}
}
return super.getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
} else {
// 实体定义了@Table(name="xxx"),以name属性值为表名
return super.getIdentifier(text, name.isQuoted(), jdbcEnvironment);
}
}
/**
* 判断是否前一个字符为小写字母,当前字符为大写字母,下一个字符为小写字母
*
* @param before
* @param current
* @param after
* @return
*/
private boolean isUnderscoreRequired(char before, char current, char after) {
return Character.isLowerCase(before) && Character.isUpperCase(current) && Character.isLowerCase(after);
}
/**
* 配置映射的字段名
*
* @param name
* @param jdbcEnvironment
* @return
*/
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
// 实体的属性名 or 自定义的@Column name属性值
String text = name.getText();
if (Character.isUpperCase(text.charAt(0))) {
// 大写字母下划线分隔命名策略,有在实体字段上自定义@Column(name="Xx_Xxx")
return new Identifier(text, name.isQuoted());
} else {
// 常见的小写驼峰式命名策略
return super.toPhysicalColumnName(name, jdbcEnvironment);
}
}
}
在 application.yml
中修改如下配置:
spring:
datasource:
username: root
password: root
url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jpa:
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
show-sql: true
hibernate:
ddl-auto: create
naming:
# 3. 自定义的命名策略
physical-strategy: cn.mariojd.jpa.naming.config.CustomNamingStrategyConfig
启动项目,查看结果,符合以上预设的实现要求
Hibernate: create table tb_teacher (id integer not null auto_increment, Name varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table teacher_class (id integer not null auto_increment, ClassName varchar(255), teacher_id integer, primary key (id)) engine=InnoDB
示例源码 如果这对您有帮助,欢迎点赞和分享,转载请注明出处