JPA,外化列,表或模式名称?

gav*_*koa 6 spring tomcat hibernate jpa

我将Spring + Hibernate + Tomcat + Oracle应用程序改编为分布式表单,需要在JPA注释中定制模式名称,类似于Spring EL:

@Entity
@Table(name = "LOSS", schema="${app.dataSchema}")
public class Loss { ... }
Run Code Online (Sandbox Code Playgroud)

${app.dataSchema}在上面的例子中寻找注释中占位符的支持.或任何其他可能性......

想法 - 拥有可以在不重新编译的情况下部署在另一个站点上的应用程序,其中保留了数据库关系/层次结构,但某些名称已更改,可以通过系统属性,JNDI或部署上下文描述符进行配置.

我看到的一个解决方案 - create view在选定的模式中 - 提供实际模式/表/列和应用程序硬编码名称之间的桥梁.

但我希望JPA/Hibernate/Spring有一些这样的配置工具......

gav*_*koa 1

Hibernate 有org.hibernate.cfg.Configuration一个扫描包和读取配置文件的点。

它使用org.hibernate.cfg.AnnotationBinder.bindClass(...)它来读取类上的注释。

这些类(8 kLOC)和方法太长了,我无法轻松阅读它们,所以我不希望对 Configuration 进行子类化...

如果注意到所有类和初始化代码都绑定到具体类而无法注入自己的类,那么使用当前的 Hibernate 4.x 架构似乎无法轻松解决我的任务。

我开始寻找替代方案并询问EBean邮件列表中配置的外部化并得到答案

public class MySchemaNamingConvention
    extends com.avaje.ebean.config.UnderscoreNamingConvention {

@Override
protected TableName getTableNameFromAnnotation(Class<?> beanClass) {
   final Table t = findTableAnnotation(beanClass);
   if (t != null && !isEmpty(t.name())) {
       String catalog = t.catalog();
       String schema = t.schema();
       //////   CUSTOM schema processing code HERE.
       //////   CUSTOM schema processing code HERE.
       //////   CUSTOM schema processing code HERE.
       return new TableName(quoteIdentifiers(catalog),
                            quoteIdentifiers(schema),
                            quoteIdentifiers(t.name()));
     }
     return null;
}
Run Code Online (Sandbox Code Playgroud)

太简单了,我告别了 Hibernate!

更新@Xstian。在迁移到 Ebean 之前,我通过设置默认模式hibernate.default_schema并广泛使用views 和synonyms 来控制哪个表可访问(Oracle):

grant select on ANOTHER_SCHEMA.TBL to MY_SCHEMA;

create or replace view MY_SCHEMA.TBL as select * from ANOTHER_SCHEMA.TBL;

create or replace synonym MY_SCHEMA.TBL for ANOTHER_SCHEMA.TBL;
Run Code Online (Sandbox Code Playgroud)

在迁移到视图/同义词期间,我仅遇到数据库约束问题。

如果您使用 Oracle - FK 约束对视图不起作用,除非您使用disable novalidate关键字添加约束并且与引用的 PK 相同:

alter view MY_SCHEMA.XXX add constraint PK_XXX primary key(ID) disable novalidate;

alter table/view MY_SCHEMA.TBL add constraint FK_XXX foreign key (XXX_ID)
  references MY_SCHEMA.XXX (ID) disable novalidate;
Run Code Online (Sandbox Code Playgroud)

对于 Oracle 来说,同义词根本不允许 FK 约束!

似乎 Hibernate 决定了数据布局,我想切换到更灵活的框架 - Ebean,但我也评估sql2ojOOQ