Hibernate5中实体映射命名策略
对象模型到关系数据库的映射的⼀部分是将对象模型中的名称映射到相应的数据库名称。
⾸先说明⼀点,Hibernate5中不再⽀持hibernate.ejb.naming_strategy属性配置,可以使⽤如下两个属性配置替换:
hibernate.implicit_naming_strategy
hibernate.physical_naming_strategy
马桶漏水怎么修
Hibernate5以前默认命名策略接⼝类⽰意图:
Hibernate5将此视为2阶段过程:
第⼀阶段是从域模型映射中确定正确的逻辑名称。逻辑名可以由⽤户显式指定(使⽤@Column或 @Table例如),也可以由
Hibernate通过ImplicitNamingStrategy契约隐式确定 。
其次是将此逻辑名解析为PhysicalNamingStrategy合约定义的物理名称。
【1】 ImplicitNamingStrategy
当实体没有显式命名它映射到的数据库表时,我们需要隐式确定该表名。或者,当某个特定属性没有显式命名它映射到的数据库列时,我们需要隐式确定该列名。org.del.naming.ImplicitNamingStrategy当映射未提供显式名称时,有⼀些规则⽤于确定逻辑名称的⽰例。
① ImplicitNamingStrategy的实现
Hibernate定义了多个ImplicitNamingStrategy实现。应⽤程序也可以插⼊⾃定义实现。有多种⽅法可
以指定要使⽤的ImplicitNamingStrategy。
⾸先,应⽤程序可以使⽤hibernate.implicit_naming_strategy配置设置指定实现,该配置设置接受:
⽤于开箱即⽤的实现的预定义“短名称”
default
for org.del.naming.ImplicitNamingStrategyJpaCompliantImpl- 别名jpa
jpa
for org.del.naming.ImplicitNamingStrategyJpaCompliantImpl- 符合JPA 2.0标准的命名策略
legacy-hbm
for org.del.naming.ImplicitNamingStrategyLegacyHbmImpl- 符合原始的Hibernate NamingStrategy legacy-jpa
for org.del.naming.ImplicitNamingStrategyLegacyJpaImpl- 符合为JPA 1.0开发的遗
留NamingStrategy,遗憾的是,在很多⽅⾯都不清楚隐式命名规则
component-path
for org.del.naming.ImplicitNamingStrategyComponentPathImpl- 主要遵循
ImplicitNamingStrategyJpaCompliantImpl规则,除了它使⽤完整的复合路径,⽽不仅仅是结束属性部分
引⽤实现org.del.naming.ImplicitNamingStrategy的类
其次,应⽤程序和集成可以利⽤org.hibernate.boot.MetadataBuilder#applyImplicitNamingStrategy 指定要使⽤的ImplicitNamingStrategy。
② 配置ImplicitNamingStrategy
⽅法1
在Hibernate的配置信息设置的时候,如下:
Configuration config = new Configuration().configure();
config.tImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE);
⽅法⼆
ServiceRegistry rviceRegistry = new StandardServiceRegistryBuilder().build();
MetadataSources sources = new MetadataSources(rviceRegistry);
MetadataBuilder builder = MetadataBuilder();
builder.applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE);
⽅法三
SpringBoot整合JPA中在l中配置:
【2】PhysicalNamingStrategy
许多组织围绕数据库对象(表,列,外键等)的命名定义规则。PhysicalNamingStrategy的想法是帮助实现这样的命名规则,⽽不必通过显式名称将它们硬编码到映射中。
虽然ImplicitNamingStrategy的⽬的是确定⼀个名为accountNumbermap 的属性映射到accountNumber未明确指定的逻辑列名称,但PhysicalNamingStrategy的⽬的是,例如,应该说缩写物理列名称acct_num。
默认实现是简单地使⽤逻辑名称作为物理名称。但是,应⽤程序和集成可以定义此PhysicalNamingStrategy规则的⾃定义实现。PhysicalNamingStrategy 接⼝源码如下:
public interface PhysicalNamingStrategy {
public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment);
public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment);
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment);
阿迪达斯标志图片logopublic Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment);
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment);
}
后进生转化其只有⼀个实现:
public class PhysicalNamingStrategyStandardImpl implements PhysicalNamingStrategy, Serializable {
/**
* Singleton access
*/
public static final PhysicalNamingStrategyStandardImpl INSTANCE = new PhysicalNamingStrategyStandardImpl();
@Override
public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment context) {
return name;
}
@Override
public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment context) {
return name;
}
@Override
public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
return name;
}
@Override
public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) {
return name;
}
@Override
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
return name;
}
}
默认情况下,使⽤就是这种策略,将ImplicitNamingStrategy传过来的逻辑名直接作为数据库中的物理名称。它的使⽤设置与ImplicitNamingStrategy相同。
⽅法1:
在Hibernate的配置信息设置的时候,如下:
Configuration config = new Configuration().configure();
config.tPhysicalNamingStrategy(new PhysicalNamingStrategyStandardImpl());
⽅法⼆
ServiceRegistry rviceRegistry = new StandardServiceRegistryBuilder().build();
MetadataSources sources = new MetadataSources(rviceRegistry);
MetadataBuilder builder = MetadataBuilder();
builder.applyPhysicalNamingStrategy(new PhysicalNamingStrategyStandardImpl());
⽅法三
SpringBoot整合JPA中在l中配置:
如上图配置所⽰,默认情况下如果Entity中不使⽤@Column指定属性对应数据库的列名,那么将会使⽤属性作为数据库列名。实体类Ur如下:
@Entity
@Table(name = "tb_ur")
public class Ur implements Serializable{
@Id //这是⼀个主键高尔夫的起源
@GeneratedValue(strategy = GenerationType.IDENTITY)//⾃增主键
private Integer id;
private String lastName;
private String email;
//...
}
使⽤⽅法三数据库⽣成属性如下:
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) DEFAULT NULL,
`lastName` varchar(255) DEFAULT NULL,
如果我们想要将其转换成last_name,除了使⽤@Column注解外,还可以⾃定义PhysicalNamingStrategy实现。
如下所⽰:
心跳过快什么原因public class ImprovedNamingStrategy implements PhysicalNamingStrategy {
@Override
public Identifier toPhysicalCatalogName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalColumnName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalSchemaName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
public Identifier toPhysicalSequenceName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
@Override
怀孕可以吃橘子吗public Identifier toPhysicalTableName(Identifier identifier, JdbcEnvironment jdbcEnv) {
return convert(identifier);
}
private Identifier convert(Identifier identifier) {
if (identifier == null || Text()==null||Text().equals("")) {
return identifier;
}
String regex = "([a-z])([A-Z])";
快乐伴我成长
String replacement = "$1_$2";
String newName = Text().replaceAll(regex, replacement).toLowerCa();
Identifier(newName);
}
}
【3】SpringBoot中推荐的Spring 命名策略
SpringBoot包下主要有两个:SpringImplicitNamingStrategy和 SpringPhysicalNamingStrategy。
舌苔厚重① SpringImplicitNamingStrategy
其继承默认的ImplicitNamingStrategyJpaCompliantImpl ,源码如下:
public class SpringImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl {
@Override
public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
String name = OwningPhysicalTableName() + "_"
+ AssociationOwningAttributePath().getProperty();
return toIdentifier(name, BuildingContext());
}
}