Java Hibernate@Table注释中的动态模式

Java Hibernate@Table注释中的动态模式,java,hibernate,Java,Hibernate,假设您在两个环境中有四个MySQL数据库模式: foo(产品数据库) bar(正在对foodb进行重组) foo_beta(测试数据库) 和bar_beta(新结构的测试数据库) 此外,假设您有一个在实体上带有Hibernate注释的Spring Boot应用程序,如下所示: @Table(name="customer", schema="bar") public class Customer { ... } @Table(name="customer", schema="foo") pu

假设您在两个环境中有四个MySQL数据库模式:

  • foo
    (产品数据库)
  • 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\u schema
,但是。。。你用了两个。那就完了


--e、 g.
@Table(name=“customer”,schema=“${myApp.schemaName}”)
不是一个选项——(甚至有些傲慢的“没人需要这个”注释),所以如果动态定义模式是荒谬的,那我们该怎么办?除此之外,您知道,一开始就没有进入这种荒谬的场景。

您可以使用orm.xml文件覆盖在注释中声明的设置。配置maven或任何用于生成可部署构建构件的工具,以便为测试环境创建覆盖文件。

我通过向Hibernate添加对我自己的模式注释的支持,解决了此类问题。通过扩展
LocalSessionFactoryBean
(或者对于hibernate3的
AnnotationSessionFactoryBean
)来实现并不困难。注释如下所示

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

    String alias() default "";

    String group() default "";

}
使用示例

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

}

spring配置中指定了
别名
的每个组合的架构名称。

您可以尝试使用拦截器

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();  

因此,当执行ever onPrepareStatement时,将调用此代码块,并将架构名称从schema更改为schema1。

这解决了我的问题,了解更多信息