Spring与Hibernate动态建表及动态加载映射文件(无需SessionFactory Rebuild)
Spring与Hibernate动态建表及动态加载映射文件(无需SessionFactory Rebuild)
?
J.Office2有一功能是工作流支持动态表单设计,设计后可以动态生成数据库表,并且支持实时查询(单表及多表均可)。
?
????????由于J.Office2版本中采用了Hibernate作为底层的ORM框架,结合Spring框架,Spring容器启动后,SessionFactory就会被注入到各个业务的Dao层中去。
?
??????? 动态建表功能比较容易实现,我们可以new一个SessionFactory,然后把它的配置属性hibernate.hbm2ddl.auto改为update或create,就可以达到动态修改表结构的效果。
?
??????????? 但若要加入新的hbm或class,需要重新调用SessionFactoryBean来获取一个全新的SessionFactory,这种方案试过了,效果并不理想。重新加载,会导致大量的hbm或class文件重新加载,实在有点慢。并且严重影响现在注入SessionFactory的Dao。若Dao采用动态构建SessionFactory,性能又是一问题。而Hibernate没有提供SessionFactory动态加入hbm或Class文件。所以实在无计可施。
?
????? 所以最终还是回到如何扩展Hibernate的SessionFactory类中去了,这想法已经有不少开发人员尝试过,JE也有一帖子专门讨论这个。不过仅是一Demo,不完善。我们提供了两个扩展的类(修改Hibernate中的两类,使其支持动态加入配置文件,并且能实时查询。
?
我们仅需要修改两个类,一个是Configuration,在其里面加一方法,如下:
???? public void doComplie(){
??? ??? ?secondPassCompile();
??? ?}
?
???? 修改
?
在SessonFactoryImpl类中加入以下方法,(有一些变量值不能修改的,请改为可修改)
?
?我们动态加入实体,动态可进行查询,Hibernate提供几种实体的查询策略,其中一个是我们常用的pojo,若采用该方法,我们得加上hbm与class类或仅是含注解的class至hibernate的SessionFactory,这种方案并且没有问题,但会遇到当我们修改表单字段,重新生成对应的实体时,我们就会遇到原有的实体class不能在ClassLoader里卸载。使用的还是旧的Class,达不到动态查询的效果。若使用动态的ClassLoader,代码将变得很复杂。(尝试过,代码相对比较繁杂)
?
??????? 还好Hibernate提供了另一种实体查询策略,基于Map的动态实体。基于这种方式,我们配置一个一对多的表,其示例代码如下:
?
MainEntity.hbm.xml
?SubEntity.hbm.xml
?
?
?为两实体插入数据后,可动态测试如下:
?
?
MainEntity2.hbm.xml与SubEntity2.hbm.xml文件相对原来的文件增加了一些列或删除了一些列?
执行后,可以实时看到不同的结果,并且不会影响现有的dao。
?
?
1 楼 haitaohehe 2011-01-29 请教下楼主,如果扩展之后对性能的影响比例占多大呢? 2 楼 man1900 2011-02-02 由于不需要重新加载,只是把需要你加的配置文件加入,影响很小 3 楼 中国鱼tt 2011-05-13 我是我发表的评论都不提交呢 4 楼 中国鱼tt 2011-05-13 楼主,我想请问一下,你所改的hibernate源码是什么版本的?我拷贝了你的代码到相应的类里面会有错误,比如this.configuration这个变量是不存在的,getMapping()方法在Configuration类里也是没有的.... 5 楼 中国鱼tt 2011-05-13 我改的是hibernate3.3.0的 6 楼 man1900 2011-05-13 //ADD by csx for dynamic register hbm or class file to hiberate configuration
public Mapping getMapping() {
return this.mapping;
}
public Map getClassMap(){
return this.classes;
}
public Map getCollectionMap(){
return this.collections;
}
public void doComplie(){
secondPassCompile();
} 7 楼 中国鱼tt 2011-05-18 ADD by csx for dynamic register hbm or class file to hiberate configurationman1900 写道//ADD by csx for dynamic register hbm or class file to hiberate configuration
public Mapping getMapping() {
return this.mapping;
}
public Map getClassMap(){
return this.classes;
}
public Map getCollectionMap(){
return this.collections;
}
public void doComplie(){
secondPassCompile();
}
这些是你加的代码呢,还是你从hibernate里面拷贝出来的呢?除了最后一个方法 8 楼 中国鱼tt 2011-05-18 还有,SessionFactoryImpl.java类里添加的那个方法里用到了一个this.configuration变量,这个变量也没找到.... 9 楼 semmy 2011-07-29 楼主是直接修改Hibernate的Configuration类和SessionFactoryImpl类吗? 10 楼 semmy 2011-07-29 secondPassCompile();
这个方法在哪里,是干嘛用的? 11 楼 semmy 2011-07-29 semmy 写道secondPassCompile();
这个方法在哪里,是干嘛用的?
sorry,我错了,没认真看清Hibernate源码。 12 楼 semmy 2011-07-29 为什么 要改写Configuration类,Configuration类是可以继承的。 13 楼 man1900 2011-08-05 不修改该类,就不有办法修改hibernate原有的SessionFactory的实现,继承与改写是两个概念,是有区别并且有一些不能替代的。