- 浏览: 94198 次
- 性别:
- 来自: 广州
文章分类
最新评论
-
wangmengfanwangzhi:
博主,我叫王梦凡,可不可以加我个QQ(574182612)我想 ...
深入 Lucene 索引机制 -
ws2011:
期待更完整的梳理!…………
struts2中重定向中文参数乱码梳理 -
hitwangzhuo:
好东东,用上了,谢谢。
Log4j按级别输出日志到不同的文件 -
jxausea:
这是我面试时被文到的题目。当时答不出来,应该早点来看
servlet,filter顺序测试 -
robbin:
改成innodb表类型
mysql数据库select查询的时候老是被锁住,大家有什么好的建议
转自:http://ssuupv.blog.163.com/blog/static/146156722009816478603/
最近开发的一个系统,需要在不更改代码和重启系统的情况下提供对用户自动建表的支持,由于系统应用了hibernate,所以在建表同时也要建立持久化对象以及对这些对象注册,人渣我首先想倒的是 baidu和google,哪知一番搜索下来,发现都不尽入人意,于是乎,造轮子之路开始了
数据库我是采用的oracle9i,目前在比如数据库类型支持,还有对象关系支持上都很简单,不过在现有基础上进行扩展,都是可以实现的
实现步骤如下
建立class->生成hbm.xml->在Hibernate'config里面注册持久化类->通知SessionFactory持久化类的新增
1 准备
首先准备基础数据,我建立了几个类来对生成的表和属性做描述 这些描述都将作为传输传递给class生成方法和hbm.xml的生成方法
RenderClass 描述要生成的实体类 属性如下
RenderProperty 就是properties集合的内容 属性如下
2 生成class
采用ASM 生成
Java代码
3 生成hbm.xml
生成这种事情,当然是交给模板了,我这里用的是Freemarker,在这里,我要感谢freemarker的开发组,感谢webwork 感谢XXCMS系统对freemarker以及其他模板语言的大力推广,,感谢。。。。(省略100字)
模板嘛,肯定不仅仅是应用在web环境的,看看源代码下的freemarker.cache包,恩,不错,freemarker团队确实是有一定“野心”的 首先是渲染的实现
Java代码
然后就是准备模板了,首先声明,我这个模板写得简单粗陋之极,不过粗陋简单不正是人渣偶的终极处世之道么,何况只实现几个简单功能,仅仅是针对测试而已嘛,何必搞得那么正规严肃了,嘿嘿
Html代码
4 注册
首先是对生成的hbm.xml的注册,比如,我获取倒Hibernate的一个config以后
Java代码
然后就是要通知sessionFactory,新增了持久类,目前很多方法都是重启sessionfactory,就是关闭当前 sessionFactory ,然后根据config build一个新的sessionFactory出来,但是,这种情况感觉总不那么完美,虽然这个过程持续不到多长时间,但用户每增一个表就close然后build一个,单说用户体验,人家正在提交数据了,你把这个给close了....
但目前hibernate包的 sessionFactory 确实没提供这种对持久类的add支持,XX伟人说过:没有条件 创造条件也要上,于是乎,拿起你的键盘,启动 editplus,向hibernate3的源码砍去。。
其实,改动地方也不大。
Java代码
一是,改动Configuration,三句话
然后是SessionFactoryImpl 我们要让他知道,这个世界上还存在很多未知的来客,需要你去主动了解。。。。
增加代码如下
Java代码
最后遗留的是hbm.xml在cfg.xml的注册,以保证系统重启后可以顺利加载新增的持久化配置
Java代码
Java代码
大功告成 ,先运行一个小周天
最后是总结测试,写个junit 搞定 代码如下:
Java代码
最近开发的一个系统,需要在不更改代码和重启系统的情况下提供对用户自动建表的支持,由于系统应用了hibernate,所以在建表同时也要建立持久化对象以及对这些对象注册,人渣我首先想倒的是 baidu和google,哪知一番搜索下来,发现都不尽入人意,于是乎,造轮子之路开始了
数据库我是采用的oracle9i,目前在比如数据库类型支持,还有对象关系支持上都很简单,不过在现有基础上进行扩展,都是可以实现的
实现步骤如下
建立class->生成hbm.xml->在Hibernate'config里面注册持久化类->通知SessionFactory持久化类的新增
1 准备
首先准备基础数据,我建立了几个类来对生成的表和属性做描述 这些描述都将作为传输传递给class生成方法和hbm.xml的生成方法
RenderClass 描述要生成的实体类 属性如下
className 类名 tableName 对应表名 properties 属性集合
RenderProperty 就是properties集合的内容 属性如下
name 属性名称 type java类型 field 字段名 primary 是否主键 sequence 对应ID生成的sequence length 对应长度
2 生成class
采用ASM 生成
Java代码
/** * 根据传入参数创建CLASS文件 * * @param 类名 * @param 保存路径 * @param 属性描述 * @return Class */ public Class build(String clsname,String savepath,Collection properties) { Class cls = null; try { String classname = BuildUtil.transferClassName(clsname); ClassWriter cw = new ClassWriter(false); //建立构造函数 cw.visit(V1_1, ACC_PUBLIC, classname, null, "java/lang/Object", null); MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); mw.visitVarInsn(ALOAD, 0); mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); mw.visitInsn(RETURN); mw.visitMaxs(1, 1); mw.visitEnd(); BuildProperty property = null; String propertytype = null; String propertyname = null;; //建立属性 Iterator iterator = properties.iterator(); while (iterator.hasNext()) { //建立属性对应的类变量 property = (BuildProperty)iterator.next(); propertytype = BuildUtil.transferClassName(property.getType()); propertyname = WordUtils.capitalize(property.getName()); cw.visitField(ACC_PRIVATE, property.getName(), "L"+propertytype+";", null, null).visitEnd(); //建立get方法 mw = cw.visitMethod(ACC_PUBLIC, "get"+propertyname, "()L"+propertytype+";", null, null); mw.visitCode(); mw.visitVarInsn(ALOAD, 0); mw .visitFieldInsn(GETFIELD, classname, property.getName(), "L"+propertytype+";"); mw.visitInsn(ARETURN); mw.visitMaxs(1, 1); mw.visitEnd(); //建立set方法 mw = cw.visitMethod(ACC_PUBLIC, "set"+propertyname, "(L"+propertytype+";)V", null, null); mw.visitCode(); mw.visitVarInsn(ALOAD, 0); mw.visitVarInsn(ALOAD, 1); mw .visitFieldInsn(PUTFIELD, classname, property.getName(), "L"+propertytype+";"); mw.visitMaxs(2, 2); mw.visitInsn(RETURN); mw.visitEnd(); } cw.visitEnd(); byte[] code = cw.toByteArray(); if (savepath!=null) { Assistant.createNewFile(savepath); FileOutputStream fos = new FileOutputStream(savepath); fos.write(code); fos.close(); } cls = this.defineClass(clsname, code, 0, code.length); return cls; } catch (Throwable e) { e.printStackTrace(); } return cls; }
3 生成hbm.xml
生成这种事情,当然是交给模板了,我这里用的是Freemarker,在这里,我要感谢freemarker的开发组,感谢webwork 感谢XXCMS系统对freemarker以及其他模板语言的大力推广,,感谢。。。。(省略100字)
模板嘛,肯定不仅仅是应用在web环境的,看看源代码下的freemarker.cache包,恩,不错,freemarker团队确实是有一定“野心”的 首先是渲染的实现
Java代码
package com.mit.cooperate.core.asm.render; import java.io.File; import java.io.FileOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import javax.servlet.ServletContext; import com.mit.cooperate.core.util.Assistant; import freemarker.cache.ClassTemplateLoader; import freemarker.template.Configuration; import freemarker.template.ObjectWrapper; import freemarker.template.SimpleHash; import freemarker.template.Template; import freemarker.template.TemplateExceptionHandler; /** * freeMarker模板渲染 * @author courser.tijichen */ public class FreemarkerRender implements Render{ private Configuration templateconfig; public FreemarkerRender() { this.initialize(); } /** * 初始化freemarker配置 * */ public void initialize() { try { if (templateconfig==null) { templateconfig = new Configuration(); templateconfig.setTemplateExceptionHandler(TemplateExceptionHandler.HTML_DEBUG_HANDLER); templateconfig.setObjectWrapper(ObjectWrapper.DEFAULT_WRAPPER); templateconfig.setTemplateLoader(new ClassTemplateLoader(this.getClass(),"/")); templateconfig.setTemplateUpdateDelay(1200); templateconfig.setDefaultEncoding("gb2312"); templateconfig.setLocale(new java.util.Locale("zh_CN")); templateconfig.setNumberFormat("0.##########"); } } catch (Exception e) {} } /** * 渲染 * */ public void render(RenderClass target,String template,String outpath) { try { StringWriter writer = new StringWriter(); Template tl = templateconfig.getTemplate( template, templateconfig.getLocale()); SimpleHash root = new SimpleHash(); root.put("entity", target); tl.process(root, writer); Assistant.createNewFile(outpath); FileOutputStream fos = new FileOutputStream(outpath); PrintWriter pwriter = new PrintWriter(fos); pwriter.write(writer.toString()); pwriter.close(); fos.close(); } catch (Exception ex) { ex.printStackTrace(); } } }
然后就是准备模板了,首先声明,我这个模板写得简单粗陋之极,不过粗陋简单不正是人渣偶的终极处世之道么,何况只实现几个简单功能,仅仅是针对测试而已嘛,何必搞得那么正规严肃了,嘿嘿
Html代码
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="${entity.className}" table="${entity.tableName}"> <#if entity.properties?exists> <#list entity.properties as property> <#if property.primary> <id name="${property.name}" type="${property.type}"> <#else> <property name="${property.name}" type="${property.type}"> </#if> <#if property.type=="java.lang.String"> <column name="${property.field?upper_case}" <#if property.length?exists>length="${property.length}"</#if>></column> <#elseif property.type=="java.util.Date"> <column name="${property.field?upper_case}" length=7></column> <#elseif property.type=="java.lang.Long" || property.type=="java.lang.Integer" || property.type=="java.lang.Short"> <column name="${property.field?upper_case}" <#if property.length?exists>precision="${property.length}"</#if> scale="0"></column> </#if> <#if property.primary==true> <#if property.sequence?exists> <generator class="sequence"> <param name="sequence">${property.sequence}</param> </generator> </#if> </id> <#else> </property> </#if> </#list> </#if> </class> </hibernate-mapping>
4 注册
首先是对生成的hbm.xml的注册,比如,我获取倒Hibernate的一个config以后
Java代码
URL url = this.getClass().getResource("/com/mit/test/person.hbm.xml"); config.addURL(url);
然后就是要通知sessionFactory,新增了持久类,目前很多方法都是重启sessionfactory,就是关闭当前 sessionFactory ,然后根据config build一个新的sessionFactory出来,但是,这种情况感觉总不那么完美,虽然这个过程持续不到多长时间,但用户每增一个表就close然后build一个,单说用户体验,人家正在提交数据了,你把这个给close了....
但目前hibernate包的 sessionFactory 确实没提供这种对持久类的add支持,XX伟人说过:没有条件 创造条件也要上,于是乎,拿起你的键盘,启动 editplus,向hibernate3的源码砍去。。
其实,改动地方也不大。
Java代码
一是,改动Configuration,三句话
public Mapping getMapping() { return this.mapping; }
然后是SessionFactoryImpl 我们要让他知道,这个世界上还存在很多未知的来客,需要你去主动了解。。。。
增加代码如下
Java代码
public void addPersistentClass(PersistentClass model,Mapping mapping) { if ( !model.isInherited() ) { IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator( settings.getDialect(), settings.getDefaultCatalogName(), settings.getDefaultSchemaName(), (RootClass) model ); if (!identifierGenerators.containsKey(model.getEntityName())) identifierGenerators.put( model.getEntityName(), generator ); } model.prepareTemporaryTables( mapping, settings.getDialect() ); String cacheRegion = model.getRootClass().getCacheRegionName(); CacheConcurrencyStrategy cache = CacheFactory.createCache( model.getCacheConcurrencyStrategy(), cacheRegion, model.isMutable(), settings, properties ); if (cache!=null) allCacheRegions.put( cache.getRegionName(), cache.getCache() ); EntityPersister cp = PersisterFactory.createClassPersister(model, cache, this, mapping); if ( cache != null && cache.getCache() instanceof OptimisticCache ) { ( ( OptimisticCache ) cache.getCache() ).setSource( cp ); } entityPersisters.put( model.getEntityName(), cp ); }
最后遗留的是hbm.xml在cfg.xml的注册,以保证系统重启后可以顺利加载新增的持久化配置
Java代码
/** * 把hbm.xml的路径加入到cfg.xml的mapping结点 * * @param cfg.xml的路径 * @param hbm.xml的路径 */ public static void updateHbmCfg(URL url,String hbm) { try { SAXReader reader = new SAXReader(); Document doc = reader.read(url); Element element = (Element)doc.getRootElement() .selectSingleNode("session-factory"); Element hbmnode = element.addElement("mapping"); hbmnode.addAttribute("resource", hbm); String filepath = url.getFile(); if (filepath.charAt(0)=='/') filepath = filepath.substring(1); FileOutputStream outputstream = new FileOutputStream(filepath); XMLWriter writer = new XMLWriter(outputstream); writer.write(doc); outputstream.close(); } catch (Exception e) { e.printStackTrace(); } }
Java代码
大功告成 ,先运行一个小周天
最后是总结测试,写个junit 搞定 代码如下:
Java代码
package com.mit.cooperate.core.hibernate; import junit.framework.TestCase; import java.net.URL; import java.util.ArrayList; import org.apache.commons.beanutils.PropertyUtils; import org.hibernate.Session; import org.hibernate.cfg.Configuration; import org.hibernate.SessionFactory; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.impl.SessionFactoryImpl; import org.hibernate.mapping.PersistentClass; import org.hibernate.Transaction; import com.mit.cooperate.core.asm.*; import com.mit.cooperate.core.asm.render.*; public class HibernateTest extends TestCase { private Configuration config; private SessionFactory factory; public void setUp() { URL url = this.getClass().getResource("/com/mit/cooperate/core/hibernate/hibernate.cfg.xml"); config = new Configuration().configure(url); factory = config.buildSessionFactory(); } public void testBuild() throws Exception { //持久类对象描述 RenderClass rc = new RenderClass(); ArrayList list = new ArrayList(); RenderProperty property = new RenderProperty(); //添加主键 property.setName("oid"); property.setField("oid"); property.setLength(new Integer(15)); property.setPrimary(true); property.setType(Long.class.getName()); property.setSequence("SEQ_PERSON"); list.add(property); //添加一个name字段 property = new RenderProperty(); property.setName("name"); property.setType(String.class.getName()); property.setField("name"); property.setLength(new Integer(20)); list.add(property); rc.setProperties(list); //类名 rc.setClassName("com.mit.test.Person"); rc.setTableName("person"); //开始生成class POBuildUtil util = new POBuildUtil(); util.build(rc.getClassName(),"E:\\cpc\\source\\cooperateCore\\com\\mit\\test\\Person.class",list); //实例化一个person Object person = Class.forName("com.mit.test.Person").newInstance();//hbmcls.newInstance(); //开始生成hbm.xml FreemarkerRender render = new FreemarkerRender(); render.render(rc, Templates.TEMPLATE_HIBERNATE3, "E:\\cpc\\source\\cooperateCore\\com\\mit\\test\\person.hbm.xml"); URL url = this.getClass().getResource("/com/mit/test/person.hbm.xml"); config.addURL(url); //更新hibernate.cfg.xml HibernateUtil.updateHbmCfg( this.getClass().getResource("/com/mit/cooperate/core/hibernate/hibernate.cfg.xml"), "com/mit/test/person.hbm.xml"); PersistentClass model = config.getClassMapping("com.mit.test.Person"); //sessionFactory哪下子,快接纳person爷爷进去 ((SessionFactoryImpl)factory).addPersistentClass(model, config.getMapping()); //生成数据库 SchemaExport export = new SchemaExport(config,((SessionFactoryImpl)factory).getSettings()); export.execute(true, true,false,true); //测试一下,随便给个名字什么的 PropertyUtils.setProperty(person, "name", "chenzhi"); Session session = factory.openSession(); Transaction tran = session.beginTransaction(); try { //保存 session.save(person); tran.commit(); } catch (Exception e) { e.printStackTrace(); tran.rollback(); } finally { session.close(); } } public void tearDown() { factory.close(); } }
相关推荐
HibernateSessionFactory.java
Hibernate中的sessionFactory
Session s= HibernateSessionFactory.getSession(); 就是Hibernate的工具java类
hibernate中的SessionFactoryhibernate中的SessionFactoryhibernate中的SessionFactory
用于获得Session会话及关闭Session会话
Hibernate中涉及到的增加,删除,查询,修改,操作.
一个实例小工程,讲解的是将hibernate的sessionFactory交给spring管理的配置方法
NULL 博文链接:https://chaoyi.iteye.com/blog/2148991
修改了Hibernate的源码,可动态增加映射文件
NULL 博文链接:https://zgdkik.iteye.com/blog/1835667
(1)Configuration:用于解析hibernate.cfg.xml文件和XXXXX.hbm.xml文件,并创建SessionFactory对象。Configuration对象用于配置并且启动Hibernate。Hibernate应用通过Configuration实例来指定对象--关系映射文件的...
(5)创建Hibernate的SessionFactory类。 (6)通过SessionFactory创建Session实例。 (7)通过创建的Session实例进行持久化对象的管理。 (8)通过创建的Transaction实例进行事务管理。 (9)通过创建的Query或...
SessionFactory接口 SessionFactory接口负责初始化Hibernate。它充当数据存储源的代理,并负责创建Session对象。这里用到了工厂模式。需要注意的是SessionFactory并不是轻量级的,因为一般情况下,一个项目通常只...
在Hibernate中使用两极缓存结构,第一级缓存是Session级别的缓存,Session级别的缓存是由Hibernate管理的,一般情况下无需进行干预.第二级缓存是 SessionFactory级别的缓存,SessionFactory级的缓存可以进行配置和...
hibernate概述,hibernate入门Demo,hibernate配置文件详解(全局配置,实体类映射配置),配置实体规则,核心API详解(Configuration,sessionFactory,session,Transaction),hibernate中的对象状态以及刷新能缓存机制 ...
Spring文件中的 SessionFactory中 加入为了能得到同一个Session
//该方法将到classpath下解析hibernate.cfg.xml中的配置,如果不用Hibernate默认的配置文件名和路径,可在该方法中指定Hibernate配置文件的名称和路径 2.用Configuration对象获取SessionFactory和Session对象:...