Spring和Hibernate动态建表及动态加载映射文件(无需Session factory...(一)

2014-11-24 08:56:38 · 作者: · 浏览: 2

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类中加入以下方法,(有一些变量值不能修改的,请改为可修改)

Java代码
//add by csx
public void addNewConfig(Configuration cfg){
log.info("add NewConfig.....");

Mapping mapping=this.configuration.getMapping();
this.filters.putAll( cfg.getFilterDefinitions() );
//Generators:
Iterator classes = cfg.getClassMappings();
while ( classes.hasNext() ) {
PersistentClass model = (PersistentClass) classes.next();

if ( !model.isInherited() ) {
IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator(
settings.getDialect(),
settings.getDefaultCatalogName(),
settings.getDefaultSchemaName(),
(RootClass) model
);
identifierGenerators.put( model.getEntityName(), generator );
}
}

///////////////////////////////////////////////////////////////////////
// Prepare persisters and link them up with their cache
// region/access-strategy

String cacheRegionPrefix = settings.getCacheRegionPrefix() == null "" : settings.getCacheRegionPrefix() + ".";

Map entityAccessStrategies = new HashMap();
Map tmpEntityPersisters=new HashMap();
Map tmpClassMetadata=new HashMap();


this.configuration.getClassMap().putAll(cfg.getClassMap());
classes = cfg.getClassMappings();

while ( classes.hasNext() ) {

PersistentClass model = (PersistentClass) classes.next();

model.prepareTemporaryTables( mapping, settings.getDialect() );
String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();

// cache region is defined by the root-class in the hierarchy...
EntityRegionAccessStrategy accessStrategy = ( EntityRegionAccessStrategy ) entityAccessStrategies.get( cacheRegionName );
if ( accessStrategy == null && settings.isSecondLevelCacheEnabled() ) {
AccessType accessType = AccessType.parse( model.getCacheConcurrencyStrategy() );
if ( accessType != null ) {

log.trace( "Building cache for entity data [" + model.getEntityName() + "]" );
EntityRegion entityRegion = settings.getRegionFactory().buildEntityRegion( cacheRegionName, properties, Cac