【问题标题】:Spring Boot JPA externalizing the schema name to property fileSpring Boot JPA 将模式名称外部化为属性文件
【发布时间】:2019-04-29 13:09:05
【问题描述】:

我的 Spring Boot 应用程序有 2 个模式,我像这样在 Entity 类中对其进行硬编码

@Entity
@Table(name"TABLE_NAME_1", schema="SCHEMA_NAME_1")
public class EntityName1{
...
}

@Entity
@Table(name"TABLE_NAME_2", schema="SCHEMA_NAME_2")
public class EntityName2{
...
}

问题是这个模式名称在每个版本中都会不断变化。因此,每次发布后,我们都必须到这里来对实体文件的架构名称进行必要的更改。

现在我想我们可以在 Spring Boot 中配置 default_schema 但这不起作用,因为我们需要将两个模式名称都外部化。

有什么方法可以使用这样的东西: @实体 @Table(name"TABLE_NAME_1", schema="{{default.schema_1}}") 公共类 EntityName1{ ... }

@Entity
@Table(name"TABLE_NAME_2", schema="{{default.schema_2}}")
public class EntityName2{
...
}

我们在外部文件中定义 default.schema_1 和 default.schema_2。

【问题讨论】:

  • 这就是为什么 JPA 允许您将 SCHEMA 信息放入 orm.xml 然后您只需更新该映射文件,而不是将其全部静态硬编码到需要重新编译的类中的原因之一!

标签: hibernate spring-boot jpa spring-data-jpa spring-data


【解决方案1】:

请试试这个...

  1. 创建类 SystemProps
public class SystemProps {

    private static Map<String,String> props = null;

    public static void loadPropsAll(){
        props = new HashMap<>();
        File file = null;
        try {
            file = ResourceUtils.getFile("classpath:application.properties");
            loadProps(file,props);
            String x = SystemProperties.get("spring.profiles.active");
            if(x != null) {
                file = ResourceUtils.getFile("classpath:application-" + x + ".properties");
                loadProps(file, props);
            }
        }catch (Exception e){e.printStackTrace();}finally {
        }
    }

    private static void loadProps(File file, Map<String,String> props){
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader(file));
            while (br.ready()){
                String line = br.readLine();
                System.out.println(line);
                if(!line.startsWith("#") && line.indexOf("=")!=-1){
                    props.put(""+line.split("=")[0].trim(), line.split("=")[1].trim());
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static String getProp(String name){
        if(props==null)
            loadPropsAll();
        return props.get(name);
    }
}
  1. 为 jpa 创建自定义命名策略
public class CustomPhysicalNamingStrategy extends SpringPhysicalNamingStrategy {
    @Override
    public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
        if(name.getText().startsWith("$")){
            String x = name.getText().replace("$","").replaceAll("\\{","").replaceAll("}","");
            String schema = SystemProps.getProp(x);
            return super.toPhysicalSchemaName(new Identifier(schema,name.isQuoted()), jdbcEnvironment);
        }
        return super.toPhysicalSchemaName(name, jdbcEnvironment);
    }
}
  1. 在 application.properties 文件中添加属性...
spring.jpa.hibernate.naming.physical-strategy=my.package.CustomPhysicalNamingStrategy

my_schema_name_property=SCHEMA_NAME_2

现在可以使用了

@Entity
@Table(name"TABLE_NAME_1", schema="${my_schema_name_property}")
public class EntityName1{
...
}

【讨论】:

    【解决方案2】:

    您只能通过反射在运行时更改模式的值(或任何其他注释值)。例如如何做到这一点看here

    然后您可以创建一个实现 ApplicationListener&lt;ApplicationReadyEvent&gt; 的 bean,该 bean 将执行 onApplicationEvent 方法,在您的情况下,该方法将在您的应用程序启动后更改特定实体类的架构值。

    【讨论】:

      猜你喜欢
      • 2018-02-21
      • 1970-01-01
      • 2020-07-30
      • 2015-06-26
      • 2020-01-27
      • 2020-07-25
      • 2018-10-25
      • 1970-01-01
      • 2015-05-14
      相关资源
      最近更新 更多