想象一下,您在两个环境中有四个MySQL数据库模式:
foo
(prod db),bar
(正在进行的foo
db重组,foo_beta
(测试数据库),bar_beta
(新结构的测试数据库)。此外,假设您在实体上有一个带有Hibernate注释的Spring Boot应用程序,如下所示:
@Table(name="customer", schema="bar")
public class Customer { ... }
@Table(name="customer", schema="foo")
public class LegacyCustomer { ... }
在本地开发时没问题。您模仿本地环境中的生产数据库表名称。但是,然后你尝试在它上线之前演示功能,并希望将其上传到服务器。你在另一个端口启动另一个应用程序实例,并意识到这个副本需要指向“foo_beta”和“bar_beta”,而不是“foo”和“bar”!该怎么做!
如果您在应用中只使用了一个架构,那么您可以将架构全部放在一起并指定hibernate.default_schema
,但是......您正在使用两个架构。那就好了。
Spring EL - e.g。 @Table(name="customer", schema="${myApp.schemaName}")
不是一个选项 - (甚至有些傲慢的“没有人需要这个”评论),所以如果动态定义模式是荒谬的,那么它会做什么?除此之外,你知道,首先不要陷入这种荒谬的场景。
答案 0 :(得分:1)
我通过在Hibernate中添加对自己的架构注释的支持来解决这类问题。通过扩展LocalSessionFactoryBean(或Hibernate 3的AnnotationSessionFactoryBean)来实现它并不是很难。注释看起来像这样
@Target(TYPE)
@Retention(RUNTIME)
public @interface Schema {
String alias() default "";
String group() default "";
}
使用
的示例@Entity
@Table
@Schema(alias = "em", group = "ref")
public class SomePersistent {
}
在弹簧配置中指定了alias
和group
的每个组合的模式名称。
答案 1 :(得分:1)
您可以尝试使用拦截器
public class CustomInterceptor extends EmptyInterceptor {
@Override
public String onPrepareStatement(String sql) {
String prepedStatement = super.onPrepareStatement(sql);
prepedStatement = prepedStatement.replaceAll("schema", "Schema1");
return prepedStatement;
}
}
将此拦截器添加为会话对象
Session session = sessionFactory.withOptions().interceptor(new MyInterceptor()).openSession();
所以发生的事情是,一旦执行onPrepareStatement,就会调用此代码块,并且模式名称将从模式更改为schema1。
答案 2 :(得分:0)
您可以使用orm.xml文件覆盖在注释中声明的设置。配置maven或您用于生成可部署构建工件的任何内容,以便为测试环境创建覆盖文件。