JPA,外部化列,表或模式名称? [英] JPA, externalizing column, table or schema names?

查看:98
本文介绍了JPA,外部化列,表或模式名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  @Entity 
@Table(name =LOSS,schema =$ {app.dataSchema})
public class Loss {...}

我在 $ {app.dataSchema}

想法 - 使应用程序可以在不重新编译的情况下部署到另一个站点,保留DB关系/层次结构,但某些名称会更改并且可以通过系统属性,JNDI或部署上下文描述符来配置。



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

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

解决方案

Hibernate有 org.hibernate.cfg.Configuration 这是扫描包和配置文件被读取的地方。



它使用 org.hibernate.cfg.AnnotationBinder.bindClass(.. 。)它读取关于类的注解。



这些类(8 kLOC)和方法很长,所以我不能轻松读取它们,所以我没有希望划分Configurati on ...

如果注意到所有类和初始化代码绑定到具体类而没有注入自己的可能性,似乎我的任务不能用当前的Hibernate轻松解决4.x体系结构。



我开始寻找替代品并询问关于 EBean 邮件列表和获得答案

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

@Override
protected TableName getTableNameFromAnnotation(Class<?> beanClass){
final Table t = findTableAnnotation(beanClass); (t!= null&&!isEmpty(t.name())){
String catalog = t.catalog();
String schema = t.schema();
////// CUSTOM模式处理代码在这里。
////// CUSTOM模式处理代码在这里。
////// CUSTOM模式处理代码在这里。
返回新的TableName(quoteIdentifiers(catalog),
quoteIdentifiers(schema),
quoteIdentifiers(t.name()));
}
返回null;
}

这么容易,我说再见Hibernate吧!



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

  grant select on ANOTHER_SCHEMA。 TBL到MY_SCHEMA; 

创建或替换视图MY_SCHEMA.TBL作为select * from ANOTHER_SCHEMA.TBL;

为ANOTHER_SCHEMA.TBL创建或替换同义词MY_SCHEMA.TBL;

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



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



  alter view MY_SCHEMA.XXX添加约束PK_XXX主键(ID)禁用novalidate; 

alter table / view MY_SCHEMA.TBL添加约束FK_XXX外键(XXX_ID)
引用MY_SCHEMA.XXX(ID)disable novalidate;

同义词不允许Oracle的FK约束!



似乎Hibernate决定了数据布局,我认为要切换到更灵活的框架--Ebean,但我也要评估 sql2o jOOQ


I adapt Spring+Hibernate+Tomcat+Oracle application to distributed form and need to make schema names customizable in JPA annotations, something like with Spring EL:

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

I look for support of placeholders in annotation like ${app.dataSchema} in above example. Or any other possibility...

Idea - to have application that can be deployed on another site without recompilation, where preserved DB relations/hierarchy, but some names are changed and can be configured by system properties, JNDI or deploy context descriptor.

One solution that I see - to create view in selected schema - to provide bridge between actual schema/table/column and application hard-coded names.

But I hope that JPA/Hibernate/Spring have some instruments for such configuration...

解决方案

Hibernate has org.hibernate.cfg.Configuration which is a point where packages are scanned and config files are read.

It uses org.hibernate.cfg.AnnotationBinder.bindClass(...) which read annotations on classes.

These classes (8 kLOC) and methods so long that I can't read them easy so I have no hope to subclass Configuration...

Ever if note that all classes and initialisation code binded to concrete classes without possibility to inject own, seems my task can't be solved easy with current Hibernate 4.x architecture.

I start looking for alternatives and ask about externaliztion of config in EBean mailing list and got answer:

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;
}

So damn easy that I say good bye to Hibernate!

UPDATE @Xstian. Before I migrate to Ebean I set default schema through hibernate.default_schema and extensively use views and synonyms to control which table will be accessible (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;

During migration to views/synonyms I have issue only with DB constraints.

In case if you use Oracle - FK constraint on view not work unless you add constraint with disable novalidate keyword and same to referenced 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;

And synonyms don't allow FK constraint at all for Oracle!

Seems that Hibernate dictate of data layout and I think to switch to more flexible framework - Ebean, but I also evaluate sql2o and jOOQ.

这篇关于JPA,外部化列,表或模式名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆