Hibernate(40)Hibernate的命名策略是什么?

Hibernate的命名策略

Hibernate的命名策略(Naming Strategy)用于定义数据库表和列的命名规则。默认情况下,Hibernate会根据实体类和属性名自动生成表名和列名,但有时候我们需要自定义这些命名规则以符合特定的命名约定或数据库要求。

默认命名策略

Hibernate 5.x及更高版本提供了一些内置的命名策略,如ImplicitNamingStrategyPhysicalNamingStrategy,用于分别处理隐式和物理命名。

  • ImplicitNamingStrategy:用于决定在没有明确指定表名或列名的情况下,如何从实体类名和属性名生成默认的表名和列名。
  • PhysicalNamingStrategy:用于决定最终采用的物理表名和列名,可以用于将隐式命名策略生成的名进行进一步的转换(如大小写转换、添加前缀或后缀等)。

自定义命名策略示例

步骤一:创建自定义命名策略

我们可以通过实现PhysicalNamingStrategy接口来创建自定义的物理命名策略。

java 复制代码
package com.example.naming;

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

public class CustomPhysicalNamingStrategy implements PhysicalNamingStrategy {

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

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

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return applyNamingStrategy(name);
    }

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

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

    private Identifier applyNamingStrategy(Identifier name) {
        if (name == null) {
            return null;
        }

        // 自定义命名规则:将所有命名转换为大写,并加上前缀 "TBL_"
        String newName = "TBL_" + name.getText().toUpperCase();
        return Identifier.toIdentifier(newName);
    }
}

步骤二:配置Hibernate以使用自定义命名策略

在Hibernate配置文件hibernate.cfg.xml中,我们需要配置使用自定义的物理命名策略。

xml 复制代码
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- 数据库连接配置 -->
        <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/your_database</property>
        <property name="hibernate.connection.username">your_username</property>
        <property name="hibernate.connection.password">your_password</property>

        <!-- Hibernate 属性配置 -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- 配置自定义物理命名策略 -->
        <property name="hibernate.physical_naming_strategy">com.example.naming.CustomPhysicalNamingStrategy</property>

        <!-- 映射类 -->
        <mapping class="com.example.domain.Product"/>
    </session-factory>
</hibernate-configuration>

步骤三:定义实体类

定义一个简单的实体类Product,并观察其在数据库中的表名和列名是如何根据自定义命名策略生成的。

java 复制代码
package com.example.domain;

import javax.persistence.*;

@Entity
@Table(name = "product")
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @Column(name = "price")
    private Double price;

    public Product() {}

    public Product(String name, Double price) {
        this.name = name;
        this.price = price;
    }

    // Getters 和 Setters

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

步骤四:测试命名策略

通过一个简单的操作来测试我们的自定义命名策略。

java 复制代码
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.example.domain.Product;

public class HibernateNamingStrategyExample {
    public static void main(String[] args) {
        // 获取SessionFactory
        SessionFactory sessionFactory = HibernateUtil.getSessionFactory();

        // 插入示例数据
        insertSampleData(sessionFactory);

        // 关闭SessionFactory
        sessionFactory.close();
    }

    private static void insertSampleData(SessionFactory sessionFactory) {
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        try {
            Product product1 = new Product("Laptop", 1000.0);
            Product product2 = new Product("Smartphone", 500.0);
            session.save(product1);
            session.save(product2);
            transaction.commit();
            System.out.println("Inserted sample data");
        } catch (Exception e) {
            if (transaction != null) {
                transaction.rollback();
            }
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }
}

详细解释

  1. 自定义命名策略

    • 创建一个名为CustomPhysicalNamingStrategy的类,实现PhysicalNamingStrategy接口,覆盖所需的方法。
    • 在覆盖的方法中,定义一个命名转换的逻辑,例如将所有名字转换为大写并添加前缀"TBL_"
  2. 配置文件

    • hibernate.cfg.xml配置文件中,添加<property name="hibernate.physical_naming_strategy">com.example.naming.CustomPhysicalNamingStrategy</property>来指定自定义命名策略类。
  3. 实体类

    • 定义一个简单的实体类Product,并观察其在数据库中生成的表名和列名。
  4. 测试命名策略

    • 通过一个示例操作(如插入数据)测试自定义命名策略的效果,观察生成的数据库表名和列名是否符合预期。

通过这种方式,我们可以灵活地定义和使用自定义的命名策略,以满足特定的数据库命名规范或个人偏好。

相关推荐
Knight_AL3 小时前
Spring 事务管理:为什么内部方法调用事务不生效以及如何解决
java·后端·spring
bcbnb3 小时前
iOS代码混淆技术深度实践:从基础到高级全面解析
后端
加洛斯3 小时前
SpringSecurity入门篇(2):替换登录页与config配置
前端·后端
用户8356290780513 小时前
Python 实现 Excel 条件格式自动化
后端·python
源代码•宸3 小时前
Golang语法进阶(协程池、反射)
开发语言·经验分享·后端·算法·golang·反射·协程池
Chan164 小时前
场景题:CPU 100% 问题怎么排查?
java·数据库·redis·后端·spring
我是谁的程序员4 小时前
iOS 文件管理,在不越狱的前提下管理 iPhone / iPad 文件
后端
v***59834 小时前
springBoot连接远程Redis连接失败(已解决)
spring boot·redis·后端
桦说编程4 小时前
滑动窗口限流器的演进之路:从调度器实现到 Packed CAS
java·后端·性能优化