9

Imagine you have four MySQL database schemas across two environments:

  • foo (the prod db),
  • bar (the in-progress restructuring of the foo db),
  • foo_beta (the test db),
  • and bar_beta (the test db for new structures).

Further, imagine you have a Spring Boot app with Hibernate annotations on the entities, like so:

@Table(name="customer", schema="bar")
public class Customer { ... }

@Table(name="customer", schema="foo")
public class LegacyCustomer { ... }

When developing locally it's no problem. You mimic the production database table names in your local environment. But then you try to demo functionality before it goes live and want to upload it to the server. You start another instance of the app on another port and realize this copy needs to point to "foo_beta" and "bar_beta", not "foo" and "bar"! What to do!

Were you using only one schema in your app, you could've left off the schema all-together and specified hibernate.default_schema, but... you're using two. So that's out.

Spring EL--e.g. @Table(name="customer", schema="${myApp.schemaName}") isn't an option--(with even some snooty "no-one needs this" comments), so if dynamically defining schemas is absurd, what does one do? Other than, you know, not getting into this ridiculous scenario in the first place.

inanutshellus
  • 9,683
  • 9
  • 53
  • 71

3 Answers3

1

I have fixed such kind of problem by adding support for my own schema annotation to Hibernate. It is not very hard to implement by extending LocalSessionFactoryBean (or AnnotationSessionFactoryBean for Hibernate 3). The annotation looks like this

@Target(TYPE)
@Retention(RUNTIME)
public @interface Schema {

    String alias() default "";

    String group() default "";

}

Example of using

@Entity
@Table
@Schema(alias = "em", group = "ref")
public class SomePersistent {

}

And a schema name for every combination of alias and group is specified in a spring configuration.

v.ladynev
  • 19,275
  • 8
  • 46
  • 67
1

you can try with interceptors

public class CustomInterceptor extends EmptyInterceptor {
@Override
    public String onPrepareStatement(String sql) {
          String prepedStatement = super.onPrepareStatement(sql);
          prepedStatement = prepedStatement.replaceAll("schema", "Schema1");
          return prepedStatement;
    }
}

add this interceptor in session object as

Session session = sessionFactory.withOptions().interceptor(new MyInterceptor()).openSession();  

so what happens is when ever onPrepareStatement is executed this block of code will be called and schema name will be changed from schema to schema1.

Lokeshkumar R
  • 575
  • 5
  • 13
0

You can override the settings you declare in the annotations using a orm.xml file. Configure maven or whatever you use to generate your deployable build artifacts to create that override file for the test environment.

Lawrence McAlpin
  • 2,745
  • 20
  • 24