IT教程 ·

Hibernate入门之定名战略(naming strategy)详解

Magicodes.IE基础教程之导出Pdf

媒介

JPA和Hibernate都供应了默许映照战略,经由历程映照将每一个实体类映照到具有雷同称号的数据库表,它的每一个属性都映照到具有雷同属性的列, 然则,在现实项目开发中大概涌现与默许定名商定不婚配,也就是说我们须要变动默许值,我们应当肿么办呢?此时我们就须要细致相识Hibernate中的定名战略,本文略长,请耐烦细读。

Hibernate 5定名战略(naming strategy)

起首我们关于Hibernate 4和Hibernate 5版本中定名战略的差别作一个大的归纳综合,然后接下来以Hibernate 5中的定名战略举行细致解说。我们晓得在Hibernate 4中运用的定名战略是hibernate.ejb.naming_strategy,该战略运用的是EJB3NamingStrategy,ImprovedNamingStrategy,DefaultComponentSafeNamingStrategy和DefaultNamingStrategy来映照称号,同时EJB3NamingStrateg是默许定名战略,它供应驼峰字段和表名,在定名外键列时,它运用下划线(_)作为分隔符,比方,假如有一个称号为table1和主键为id的表,那末在table2中,外键列将被建立为table1_id,而且此EJB3NamingStrategy完成NamingStrategy接口。因为基于NamingStrategy定名战略接口所完成的上述战略照样不够天真以至于没法准确运用定名划定规矩,因而hibernate.ejb.naming_strategy不再实用,取而代之的是,引入了两种新战略来供应对定名战略的深度定制,它们是ImplicitNamingStrategy和PhysicalNamingStrategy,这两种战略离别对应的键是implicit_naming_strategy和physical_naming_strategy,Hibernate5仅供应了针对PhysicalNamingStrategy的一种完成即PhysicalNamingStrategyStandardImpl,然则针对ImplicitNamingStrategy战略(隐式定名战略)供应了几种完成。当我们未在实体中显式定义表名和列名时,将运用ImplicitNamingStrategy定名战略,个中,PhysicalNamingStrategy战略可用于显式定义实体和属性称号与数据库和列称号的映照划定规矩。

 

基于媒介的形貌,若须要一致修正成公司划定的定名划定规矩,我们固然可认为每一个实体指定表名且为每一个属性指定列名, 这须要在每一个类上运用@Table解释,并在每一个属性上运用@Column解释,我们称之为显式定名,然则对项目中大批的实体和属性实行此操纵须要大批事情,为了进步效力,我们能够调解Hibernate的定名战略才是最好体式格局,然则完成调解Hibernate中的定名战略之前,我们起首须要议论下Hibernate的逻辑定名战略和物理定名战略之间的辨别。

 

默许情况下即我们未举行任何设置的情况下,逻辑称号和物理称号是一样的,Hibernate将实体或属性称号到表或列称号的映照分为两个步骤:

【1】它起首肯定实体或属性的逻辑称号。我们能够运用@Table和@Column注解显式设置逻辑称号,假如我们不如许做,则Hibernate将运用其隐式定名战略之一。
【2】它将逻辑称号映照为物理称号。默许情况下,Hibernate运用逻辑名作为物理名,然则,我们也能够运用PhysicalNamingStrategy战略,将逻辑称号映照为遵照内部定名商定的物理称号。

以上两个步骤我置信并不难明白,那末,为何Hibernate要辨别逻辑定名战略和物理定名战略,而在JPA范例却没有呢?JPA的定名战略体式格局行之也有用,然则我们会发明Hibernate的要领供应了更大的天真性,经由历程将历程分为两个步骤,Hibernate许可我们完成转换,该转换将运用于一切属性和类。比方,假如我们的定名商定请求在一切表称号上加上“ s”,则能够在PhysicalNamingStrategy中实行此操纵,然后呢,不管我们是在@Table注解中显式指定表名,照样基于实体名隐式地指定表名,都没有任何关联。在这两种情况下,Hibernate都会在表名的末端增加“ s”。有的童鞋大概问终究终究作甚逻辑称号和物理称号呢?一言以蔽之,逻辑称号是未经任何设置情况下的称号(此时逻辑称号和物理称号雷同),而物理称号则是终究存在数据库表中的表名和列名,能够经由历程注解指定。

显式定名战略(Explicit naming strategy)

显式定名战略异常简朴,我们唯一须要做的就是用@Table注解实体类或运用@Column注解实体属性,比方以下:

@Entity
@Table(name = "student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "Id")
    private int id;
}

隐式定名战略(Implicit naming strategy)

假如我们未在注解中设置表名或列名,那末Hibernate将运用其隐式定名战略之一, 我们能够挑选以下4种差别的定名战略,4种隐式定名战略存在于包【org.hibernate.boot.model.naming】下,在细致解说以下4种隐式定名战略之前,我们须要用到以下4个类以及设置其关联,以下:

@Embeddable
public class EmbeddableElement {

    @Column(name = "quotedField")
    private String quotedField;

    @Column
    private String regularField;
}
@Entity
@Table(name = "mainTable")
public class MainEntity {

    @Id
    private long id;

    @ElementCollection
    private Set<EmbeddableElement> mainElements;

    @OneToMany(targetEntity = DependentEntity.class)
    Set<DependentEntity> dependentEntities;

    @OneToOne(targetEntity = OwnedEntity.class)
    OwnedEntity ownedEntity;
}
@Entity
@Table(name = "dependentTable")
public class DependentEntity {
    @Id
    private Long id;

    @ManyToOne
    MainEntity mainEntity;

    @ElementCollection
    @CollectionTable(name = "dependentElements")
    Set<EmbeddableElement> dependentElements;
}
@Entity(name = "owned_table")
public class OwnedEntity {
    @Id
    private Long id;

    @ElementCollection
    @CollectionTable
    Set<EmbeddableElement> ownedElements;
}

在上一节的建立Hibernate设置文件的基础上,增加对上述MainEntity、DependentEntity、OwnedEntity和EmbeddableElement对象的映照,以下:

Hibernate入门之定名战略(naming strategy)详解 IT教程 第1张

【1】jpa(ImplicitNamingStrategyJpaCompliantImpl)

它作为隐式默许定名战略,也是相符JPA 2.0范例中定义的定名战略,该范例指出实体类的逻辑称号能够是@Entity讲明中供应的称号,也能够黑白限制的类称号。关于基础属性,它运用属性称号作为逻辑称号。关于元素鸠合的逻辑称号由具有实体的类称号 + '_' +  援用实体的属性称号构成。关于衔接表的逻辑称号由具有实体的物理称号 + '_' + 援用实体的物理称号构成。上述终究生成的表以下:

create table mainTable (id bigint not null, ownedEntity_id bigint, primary key (id))

create table MainEntity_mainElements (MainEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table mainTable_dependentTable (MainEntity_id bigint not null, dependentEntities_id bigint not null, primary key (MainEntity_id, dependentEntities_id))

create table dependentTable (id bigint not null, mainEntity_id bigint, primary key (id))

create table dependentElements (DependentEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table owned_table (id bigint not null, primary key (id))

create table owned_table_ownedElements (owned_table_id bigint not null, quotedField varchar(255), regularField varchar(255))

我们看到上述所建立的元素鸠合表名为MainEntity_mainElements,此时它的逻辑称号是其具有实体的类名(MainEntity)而不是定义的物理称号(mainTable)+  '_'  + 元素鸠合属性称号构成。而关联表mainTable_dependentTable则由具有实体的物理称号(注解@Table)+ '_' + 援用实体的物理称号(注解@Table)构成。同时发明一个很有意义的问题,上述建立表名有大写的字母,现实生成到数据库中表名满是小写,不晓得这是什么原因所形成的,以下:

Hibernate入门之定名战略(naming strategy)详解 IT教程 第2张

【2】legacy-hbm(ImplicitNamingStrategyLegacyHbmImpl)

它是Hibernate的原始定名战略,但它没法辨认JPA的任何注解,然则我们能够运用Hibernate的专有设置文件和注解来定义列或实体称号,除此之外,它与上述JPA 2.0范例还存在一点差别,关于元素鸠合的逻辑称号构成雷同。关于衔接表由具有实体的物理称号 + ‘_’ + 援用实体的属性称号构成(而不再是物理称号),也就是说援用实体(或许我们可称之为衔接列)的逻辑称号为其属性称号。接下来我们将默许隐式战略修正为此隐式战略,注重不要将property节点放在mapping节点下面,不然会涌现编译毛病。

<property name="hibernate.implicit_naming_strategy">
    org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
</property>

Hibernate入门之定名战略(naming strategy)详解 IT教程 第3张

create table mainTable (id bigint not null, ownedEntity_id bigint, primary key (id))

create table MainEntity_mainElements (MainEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table mainTable_dependentEntities (MainEntity_id bigint not null, dependentEntities bigint not null, primary key (MainEntity_id, dependentEntities))

create table dependentTable (id bigint not null, mainEntity_id bigint, primary key (id))

create table dependentElements (DependentEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table OwnedEntity (id bigint not null, primary key (id))

create table OwnedEntity_ownedElements (OwnedEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

比方上述MainEntity的援用实体(援用列)dependentEntities和ownedEntity,此时两者逻辑称号就是其属性称号,所以终究我们看到和JPA 2.0范例中对照下,生成的表名为mainTable_dependentEntities、OwnedEntity和OwnedEntity_ownedElements。

【3】legacy-jpa(ImplicitNamingStrategyLegacyJpaImpl)

该战略完成了JPA 1.0范例中定义的定名战略,它与JPA 2.0范例定名战略的重要辨别在于:关于元素鸠合的逻辑称号由具有实体的物理称号 + '_'  + 援用实体的属性构成。关于衔接表的逻辑称号由具有方的物理表称号 + '_' + 援用实体的物理称号构成。legacy-jpa战略运用物理称号而不是关联援用的实体称号。

Hibernate入门之定名战略(naming strategy)详解 IT教程 第4张

create table mainTable (id bigint not null, ownedEntity_id bigint, primary key (id))

create table mainTable_mainElements (mainTable_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table mainTable_dependentTable (mainTable_id bigint not null, dependentEntities_id bigint not null, primary key (mainTable_id, dependentEntities_id))

create table dependentTable (id bigint not null, mainEntity_id bigint, primary key (id))

create table dependentElements (DependentEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table owned_table (id bigint not null, primary key (id))

create table owned_table_ownedElements (owned_table_id bigint not null, quotedField varchar(255), regularField varchar(255))

【4】component-path(ImplicitNamingStrategyComponentPathImpl)

该战略险些与JPA 2.0范例中定义的定名战略雷同,唯一的辨别在于:它在逻辑属性称号中包含了复合称号。

Hibernate入门之定名战略(naming strategy)详解 IT教程 第5张

create table mainTable (id bigint not null, ownedEntity_id bigint, primary key (id))

create table MainEntity_mainElements (MainEntity_id bigint not null, quotedField varchar(255), mainElements_regularField varchar(255))

create table mainTable_dependentTable (MainEntity_id bigint not null, dependentEntities_id bigint not null, primary key (MainEntity_id, dependentEntities_id))

create table dependentTable (id bigint not null, mainEntity_id bigint, primary key (id))

create table dependentElements (DependentEntity_id bigint not null, quotedField varchar(255), regularField varchar(255))

create table owned_table (id bigint not null, primary key (id))

create table owned_table_ownedElements (owned_table_id bigint not null, quotedField varchar(255), regularField varchar(255))

我们看到针对元素鸠合EmbeddableElement,针对regularField属性并未显式设置映照列名,此时将运用具有实体所援用实体的(鸠合属性称号 + '_' + 属性称号 )作为复合称号。

物理定名战略(PhysicalNamingStrategy)

上述是对Hibernate 5中关于4种隐式定名战略的细致引见,最好都以默许隐式定名战略作为对照,如许能更好的明白,固然我们也能够完成自定义的隐式定名战略,只需继承自上述4种隐式定名战略之一即可。回到本文开头,我们完成自定义的物理定名战略并不庞杂,我们能够完成PhysicalNamingStrategy接口,也能够扩大Hibernate的PhysicalNamingStrategyStandardImpl类,经由历程扩大Hibernate的PhysicalNamingStrategyStandardImpl越发简朴。 在以下示例中,建立一个针对每一个表都增加's'即复数的自定义物理定名战略,以下:

public class TableSuffixPhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl {

    private final static String suffix = "s";

    @Override
    public Identifier toPhysicalTableName(final Identifier identifier, final JdbcEnvironment jdbcEnv) {
        if (identifier == null) {
            return null;
        }

        final String newName = identifier.getText() + suffix;
        return Identifier.toIdentifier(newName);
    }

}

然后在Hibernate设置文件中增加对物理定名战略的自定义完成,以下:

<property name="hibernate.physical_naming_strategy">
   strategy.TableSuffixPhysicalNamingStrategy
</property>

或许完成PhysicalNamingStrategy物理定名战略接口,能够到达上述一样的结果:

public class CustomPhysicalNamingStrategy implements PhysicalNamingStrategy {

    private final static String suffix = "s";

    @Override
    public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return name;
    }

    @Override
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return name;
    }

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return jdbcEnvironment.getIdentifierHelper().toIdentifier(
                name.getText() + suffix,
                name.isQuoted()
        );
    }

    @Override
    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return name;
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        return name;
    }
}

总结

本节我们回忆了Hibernate 4中存在的定名战略以及在Hibernate 5种从新引入两种定名战略以处理在Hibernate 4中的不天真性,从而我们更轻易的完成自定义深度定制的定名战略,不管是隐式定名战略照样物理定名战略依据响应需求皆可,好了,本节我们到此结束,下节我们继承Hibernate 5探索之旅。

9种分布式ID生成之 美团(Leaf)实战

参与评论