Recherche…


Création et utilisation d'un implicitNamingStrategy personnalisé

La création d'un ImplicitNamingStrategy personnalisé vous permet d'affiner la façon dont Hibernate affectera des noms à des attributs Entity non explicitement nommés, notamment des clés étrangères, des clés uniques, des colonnes d'identifiant, des colonnes de base, etc.

Par exemple, par défaut, Hibernate va générer des clés étrangères hachées et similaires à:

FKe6hidh4u0qh8y1ijy59s2ee6m

Bien que ce ne soit souvent pas un problème, vous pouvez souhaiter que le nom soit plus descriptif, par exemple:

FK_asset_tenant

Cela peut facilement être fait avec un ImplicitNamingStrategy personnalisé.

Cet exemple étend l' ImplicitNamingStrategyJpaCompliantImpl , mais vous pouvez choisir d'implémenter ImplicitNamingStrategy si vous le souhaitez.

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl;

public class CustomNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl {

    @Override
    public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
        return toIdentifier("FK_" + source.getTableName().getCanonicalName() + "_" + source.getReferencedTableName().getCanonicalName(), source.getBuildingContext());
    }

}

Pour indiquer à Hibernate quel ImplicitNamingStrategy utiliser, définissez la propriété hibernate.implicit_naming_strategy dans votre fichier persistence.xml ou hibernate.cfg.xml comme suit:

<property name="hibernate.implicit_naming_strategy"
                  value="com.example.foo.bar.CustomNamingStrategy"/>

Ou vous pouvez spécifier la propriété dans le fichier hibernate.properties comme suit:

hibernate.implicit_naming_strategy=com.example.foo.bar.CustomNamingStrategy

Dans cet exemple, toutes les clés étrangères n'ayant pas de name explicitement défini obtiendront désormais leur nom de CustomNamingStrategy .

Stratégie de nommage physique personnalisée

Lors du mappage de nos entités sur des noms de tables de base de données, nous @Table une annotation @Table . Mais si nous avons une convention de dénomination pour nos noms de tables de base de données, nous pouvons implémenter une stratégie de dénomination physique personnalisée afin d'indiquer à hibernate de calculer les noms des tables en fonction des noms des entités sans les @Table avec @Table . Même chose pour le mappage des attributs et des colonnes.

Par exemple, notre nom d'entité est:

ApplicationEventLog

Et notre nom de table est:

application_event_log

Notre stratégie de nommage physique doit convertir les noms d'entité qui sont des cas de chameau à nos noms de table de base de données qui sont des cas de serpent. Nous pouvons y parvenir en étendant PhysicalNamingStrategyStandardImpl de hibernate:

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl {

    private static final long serialVersionUID = 1L;
    public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(addUnderscores(name.getText()), name.isQuoted());
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return new Identifier(addUnderscores(name.getText()), name.isQuoted());
    }

    protected static String addUnderscores(String name) {
        final StringBuilder buf = new StringBuilder(name);
        for (int i = 1; i < buf.length() - 1; i++) {
            if (Character.isLowerCase(buf.charAt(i - 1)) &&
                    Character.isUpperCase(buf.charAt(i)) &&
                    Character.isLowerCase(buf.charAt(i + 1))) {
                buf.insert(i++, '_');
            }
        }
        return buf.toString().toLowerCase(Locale.ROOT);
    }
}

Nous toPhysicalTableName comportement par défaut des méthodes toPhysicalTableName et toPhysicalColumnName pour appliquer notre convention de dénomination de base de données.

Pour utiliser notre implémentation personnalisée, nous devons définir la propriété hibernate.physical_naming_strategy et lui donner le nom de notre classe PhysicalNamingStrategyImpl .

hibernate.physical_naming_strategy=com.example.foo.bar.PhysicalNamingStrategyImpl

De cette façon, nous pouvons alléger notre code des annotations @Table et @Column , donc notre classe d'entité:

@Entity
public class ApplicationEventLog {
    private Date startTimestamp;
    private String logUser;
    private Integer eventSuccess;

    @Column(name="finish_dtl")
    private String finishDetails;
}

sera correctement mappé à la table de base de données:

CREATE TABLE application_event_log (
  ...
  start_timestamp timestamp,
  log_user varchar(255),
  event_success int(11),
  finish_dtl varchar(2000),
  ...
)

Comme nous l'avons vu dans l'exemple ci-dessus, nous pouvons toujours indiquer explicitement le nom de l'objet db si, pour une raison quelconque, il n'est pas conforme à notre convention de dénomination générale: @Column(name="finish_dtl")



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow