Shellbye.github.io icon indicating copy to clipboard operation
Shellbye.github.io copied to clipboard

Spring Boot JPA Hibernate 添加表名前缀 table name prefix

Open Shellbye opened this issue 6 years ago • 0 comments

JPAHibernate的帮助下,Spring用起来也和Django很像,可以自动的从model生成数据库表。我最近在项目中遇到一个需要给所有的表都加一个tb_的前缀,从网上找了找,果然可以做到,下面简单记录一下。

本项目的整个工程链接在Github,下面是最核心的文件PrefixTbNamingStrategy.class

package com.example.demo;

import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.naming.PhysicalNamingStrategy;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.springframework.context.annotation.Configuration;

import java.util.Locale;

@Configuration
public class PrefixTbNamingStrategy implements PhysicalNamingStrategy {

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

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

    @Override
    public Identifier toPhysicalTableName(Identifier name,
                                          JdbcEnvironment jdbcEnvironment) {
        Identifier identifier = apply(name, jdbcEnvironment);
        String tbName = "tb_" + identifier.toString();
        return new Identifier(tbName, identifier.isQuoted());
    }

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

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

    private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
        if (name == null) {
            return null;
        }
        StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
        for (int i = 1; i < builder.length() - 1; i++) {
            if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i),
                    builder.charAt(i + 1))) {
                builder.insert(i++, '_');
            }
        }
        return getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
    }

    /**
     * Get an identifier for the specified details. By default this method will return an
     * identifier with the name adapted based on the result of
     * {@link #isCaseInsensitive(JdbcEnvironment)}
     *
     * @param name            the name of the identifier
     * @param quoted          if the identifier is quoted
     * @param jdbcEnvironment the JDBC environment
     * @return an identifier instance
     */
    protected Identifier getIdentifier(String name, boolean quoted,
                                       JdbcEnvironment jdbcEnvironment) {
        if (isCaseInsensitive(jdbcEnvironment)) {
            name = name.toLowerCase(Locale.ROOT);
        }
        return new Identifier(name, quoted);
    }

    /**
     * Specify whether the database is case sensitive.
     *
     * @param jdbcEnvironment the JDBC environment which can be used to determine case
     * @return true if the database is case insensitive sensitivity
     */
    protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
        return true;
    }

    private boolean isUnderscoreRequired(char before, char current, char after) {
        return Character.isLowerCase(before) && Character.isUpperCase(current)
                && Character.isLowerCase(after);
    }
}

这个文件基本上copy自org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy,只在方法toPhysicalTableName上做了一个最简单的修改,实现了想要的功能。代码应该是还可以进一步精简的(比如直接继承SpringPhysicalNamingStrategy),但是这里只是记录一种思路,就不进行精简了。

这里要特别说明一下顶部的注解@Configuration,如果不加这个注解,就需要在application.properties里面添加如下一行

spring.jpa.hibernate.naming.physical-strategy=com.example.demo.PrefixTbNamingStrategy

Shellbye avatar Feb 23 '19 04:02 Shellbye