5

I have 2 schemas for my spring boot application, which I hardcode in the Entity class like this

@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{
...
}

The problem is this schema name keeps on changing every release. So after every release we have to come here and make the necessary changes on the entity file's schema name.

Now I figured we can configure default_schema in spring boot but that won't work because we need to externalize both schema names.

Is there any way we can use something like this: @Entity @Table(name"TABLE_NAME_1", schema="{{default.schema_1}}") public class EntityName1{ ... }

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

where we define the default.schema_1 and and default.schema_2 in an external file.

Swastik
  • 273
  • 3
  • 15
  • 1
    Possible duplicate of [Change database schema used by Spring Boot](https://stackoverflow.com/questions/24278659/change-database-schema-used-by-spring-boot) – Simon Martinelli Nov 27 '18 at 18:26
  • Which is one of the reasons why JPA allows you to put SCHEMA information in `orm.xml` and then you just update that mapping file, rather than hardcoding it all statically into classes that need recompiling! –  Nov 28 '18 at 11:16

2 Answers2

3

Please, try this...

  1. Create class 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. Create custom naming strategy for 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. in application.properties file add properties...
spring.jpa.hibernate.naming.physical-strategy=my.package.CustomPhysicalNamingStrategy

my_schema_name_property=SCHEMA_NAME_2

Now you can use it

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

0

You can change the value of schema (or any other annotation value for that matter) in runtime only with reflection. For example of how to do it look here.

Then you could create a bean implementing ApplicationListener<ApplicationReadyEvent> that will execute the method onApplicationEvent that in your case would change schema value on specific entity class after your application start up.

Piotr Podraza
  • 1,941
  • 1
  • 15
  • 26