討論Hibernate和模型對象
學(xué)習(xí)Hibernate時,經(jīng)常會遇到一些小問題,這里將介OSGi平臺的插件類加載機(jī)制使得Hibernate無法正確加載分布在不同插件內(nèi)部的模型對象與O/R映射文件問題的解決方法。
OpenCore是在OSGi規(guī)范上構(gòu)建的微內(nèi)核(Microkenerl),基于純組件(Pure Plugin)開放源碼企業(yè)應(yīng)用軟件平臺。
OpenCore數(shù)據(jù)層實現(xiàn)OSGi上集成Hibernate,Hibernate及其依賴庫作為一個單獨的插件,這樣帶來一個問題,就是OSGi平臺的插件類加載機(jī)制使得Hibernate無法正確加載分布在不同插件內(nèi)部的模型對象與O/R映射文件。本文討論解決方案:
模型對象(Domain Objects)插件
模型對象(Domain Objects)集中到獨立的插件(Bundle)內(nèi),Hibernate插件依賴這些模型對象插件。這是最簡單的,也是比較糟糕的方式,比較小的基于OSGi的項目可以這也作做。
Eclipse-BuddyPolicy與Eclipse-RegisterBuddy方式
Equinox(Eclipse提供的OSGi實現(xiàn))平臺特有的方式,允許插件(Bundle)聲明自己的伙伴,讓“伙伴插件”來動態(tài)加載本插件的類,這也是Hiberate與Equinox集成的官方解決方案。這種方式模型對象無需部署在單獨的插件內(nèi),與業(yè)務(wù)插件部署在一起即可,Hibernate插件也無須依賴模型對象。
具體做法如下:
首先,Hibernate插件(名稱,例如org.opengoss.orm.hibernate)聲明自身可以作為伙伴插件,自描述文件(MANIFEST.MF) 加入描述:Eclipse-BuddyPolicy: registered
然后,模型對象的業(yè)務(wù)插件中把Hibernate插件加入為伙伴,自描述文件(MANIFEST.MF) 加入描述:Eclipse-RegisterBuddy:org.opengoss.orm.hibernate
Eclipse Extension Point方式
這是我們目前實現(xiàn)的方式,通過標(biāo)準(zhǔn)的Eclipse擴(kuò)展點與擴(kuò)展機(jī)制,我們在Hibernate插件中plugin.xml配置文件中聲明下述擴(kuò)展點,在模型對象插件中聲明擴(kuò)展,例如:
Hibernate插件的啟動中,用代碼配置生成SessionFactory,代碼如下:
- public void start(BundleContext context) throws Exception {
- Configuration configuration = new Configuration().configure
(new File ("./etc/org.opengoss.database.hibernate/hibernate.cfg.xml"));- Class[] domainClasses = getDomainClasses();
- for (Class domainClass : domainClasses) {
- configuration.addClass(domainClass);
- }
- sessionFactory = configuration.buildSessionFactory();
- Dictionarynew Hashtable props.put("scope", "APPLICATION");
- props.put("uid", "Hibernate:SessionFactory");
- registration = context.registerService
(SessionFactory.class.getName(), sessionFactory, props);- }
- private Class[] getDomainClasses() throws Exception {
- List domainClasses = new ArrayList();
- IExtensionPoint point = registry.getExtensionPoint
(IConstants.DOMAIN_OBJECT_EXTENSION_POINT);- IExtension[] extensions = point.getExtensions();
- for (IExtension extension : extensions) {
- IConfigurationElement[] elements = extension.getConfigurationElements();
- for (IConfigurationElement configurationElement : elements) {
- Bundle bundle = pluginContext.getBundleBySymbolId
(extension.getNamespaceIdentifier());- Class domainClass = bundle.loadClass
(configurationElement.getAttribute("class"));- domainClasses.add(domainClass);
- }
- }
- return domainClasses.toArray(new Class[domainClasses.size()]);
- }
注意:Hibernate內(nèi)部的類加載機(jī)制實在無法令人滿意,盡管我們在這種方式中已經(jīng)加載所有的模型類對象,但Hibernate內(nèi)部仍然會調(diào)用Class.forName()去試圖加載。
【編輯推薦】