Spring Data JPA 实战 - Naming命名策略,源码跟踪

在 Spring Data JPA 中,命名策略(Naming Strategy)是指定实体类属性与数据库表字段之间的映射关系的规则。默认情况下,Spring Data JPA 使用一定的约定来生成这些映射,但如果需要定制这些映射规则,则可以通过配置自定义的命名策略来实现。

默认的命名策略

Spring Data JPA 默认使用 org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategyorg.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy 来确定实体类属性与数据库表字段之间的映射关系。这些策略遵循以下规则:

  1. 实体类名称转换为表名:默认情况下,实体类名称会被转换为小写,并且去掉首字母的大写,例如 User 类对应 users 表。
  2. 属性名称转换为字段名:属性名称默认也会被转换为小写,并且去掉首字母的大写,例如 firstName 对应 first_name 字段。

自定义命名策略

如果你希望覆盖这些默认的行为,可以自定义命名策略。这通常通过配置 Hibernate 的命名策略来实现。自定义命名策略可以通过实现 Hibernate 的 PhysicalNamingStrategyImplicitNamingStrategy 接口来完成。

自定义命名策略示例

这里是一个简单的示例,展示如何创建自定义的命名策略:

定义命名策略类
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class CustomNamingStrategy implements PhysicalNamingStrategy, ImplicitNamingStrategy {

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        // 将表名转换为全小写
        return Identifier.toIdentifier(name.getText().toLowerCase(), jdbcEnvironment);
    }

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        // 将字段名转换为全小写
        return Identifier.toIdentifier(name.getText().toLowerCase(), jdbcEnvironment);
    }

    @Override
    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        // 序列名转换规则
        return Identifier.toIdentifier(name.getText().toLowerCase(), jdbcEnvironment);
    }

    @Override
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        // schema 名称转换规则
        return name == null ? null : Identifier.toIdentifier(name.getText().toLowerCase(), jdbcEnvironment);
    }

    @Override
    public Identifier toImplicitTableName(Class<?> clazz) {
        // 类名转换为表名
        return Identifier.toIdentifier(clazz.getSimpleName().toLowerCase());
    }

    @Override
    public Identifier toImplicitColumnName(TableReference tableReference, SingularAttribute<?, ?> attribute) {
        // 属性名转换为字段名
        return Identifier.toIdentifier(attribute.getName().toLowerCase());
    }

    @Override
    public Identifier toImplicitIndexName(TableReference tableReference, Index index) {
        // 索引名转换规则
        return Identifier.toIdentifier(index.getName().toLowerCase());
    }

    @Override
    public Identifier toImplicitColumnName(TableReference tableReference, PluralAttribute<?, ?, ?> attribute) {
        // 复数属性名转换规则
        return Identifier.toIdentifier(attribute.getName().toLowerCase());
    }

    @Override
    public Identifier toImplicitKeyColumnName(TableReference tableReference, SingularAttribute<?, ?> keyAttribute) {
        // 主键字段名转换规则
        return Identifier.toIdentifier(keyAttribute.getName().toLowerCase());
    }

    @Override
    public Identifier toImplicitForeignKeyName(ForeignKey foreignKey) {
        // 外键名转换规则
        return Identifier.toIdentifier(foreignKey.getName().toLowerCase());
    }

    @Override
    public Identifier toExplicitTableName(TableReference tableReference) {
        // 显式表名转换规则
        return tableReference.getName();
    }

    @Override
    public Identifier toExplicitColumnName(ColumnReference columnReference) {
        // 显式字段名转换规则
        return columnReference.getName();
    }

    @Override
    public Identifier toExplicitIndexName(TableReference tableReference, Index index) {
        // 显式索引名转换规则
        return index.getName();
    }

    @Override
    public Identifier toExplicitKeyColumnName(TableReference tableReference, KeyColumn keyColumn) {
        // 显式主键字段名转换规则
        return keyColumn.getName();
    }

    @Override
    public Identifier toExplicitForeignKeyName(ForeignKey foreignKey) {
        // 显式外键名转换规则
        return foreignKey.getName();
    }
}
配置命名策略

接下来,你需要在 Spring Boot 的配置文件中指定这个自定义的命名策略:

spring:
  jpa:
    properties:
      hibernate:
        naming:
          physical-strategy: com.example.app.config.CustomNamingStrategy
          implicit-strategy: com.example.app.config.CustomNamingStrategy

或者在 application.properties 中:

spring.jpa.properties.hibernate.naming.physical-strategy=com.example.app.config.CustomNamingStrategy
spring.jpa.properties.hibernate.naming.implicit-strategy=com.example.app.config.CustomNamingStrategy

这里的 com.example.app.config.CustomNamingStrategy 是你的自定义命名策略类的全限定名。

源码跟踪

如果你想深入了解 Spring Data JPA 中命名策略的工作原理,可以查看相关的源码。以下是几个关键类和方法:

  1. org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties

    • 这个类包含了 Hibernate 相关的配置属性,包括命名策略。
    • 它提供了 naming() 方法来获取或设置命名策略。
  2. org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy

    • 默认的物理命名策略实现。
    • 实现了 PhysicalNamingStrategy 接口,提供了默认的命名转换逻辑。
  3. org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy

    • 默认的隐式命名策略实现。
    • 实现了 ImplicitNamingStrategy 接口,提供了默认的命名转换逻辑。
  4. org.hibernate.boot.model.naming.ImplicitNamingStrategyPhysicalNamingStrategy

    • Hibernate 的命名策略接口。
    • 定义了如何将实体类和属性名转换为数据库表名和字段名。

总结

通过上述步骤,你可以自定义 Spring Data JPA 中的命名策略来满足项目的具体需求。如果你需要更深入地了解这些组件是如何工作的,可以查看 Hibernate 和 Spring Boot 的相关源码。如果你有其他具体的问题或者需要帮助,请随时告诉我!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值