使用Shark自带的Hibernate实现代码替换DODS (2007-10-16 09:32)

来源:互联网 发布:发票软件下载 编辑:程序博客网 时间:2024/05/20 05:07
在研究工作流引擎shark的时候,在网上找了一点有关Shark的用户管理模块为Hibernate实现的资料:
 
使用Shark自带的Hibernate实现代码替换DODS:

    1.使用Hibernate的版本是2.xx,我试了2.00和2.18(2.x最后一个版本),2.00不能用,2.18可以,所以也不计较他们开发的时候具体用那个版本的Hibernate,直接用2.18即可。

    2.将hibernate2.jar和common-lang.jar加入BuildPath,common-lang.jar是Hibernate要用到的。另外要把odmg-3.0.jar、dom4j-1.4.jar、……等包都加入到ClassPath,这些包是反射的方式来调用的,没有也能编译,但是运行不了。

    3.无论打算先将哪一个模块的持久化替换成Hibernate(文中部分使用“Hibernate”指代“Shark源码中的Hibernate持久层实现”,下同),SharkTransaction和SharkUserTransaction模块的Hibernate实现是必须要最先做好的。通常SharkUtilities里面的Hibernate也要使用到,所以优先替换这三个模块,除了这三个模块,其他各个模块的实现基本不耦合。
    这里要抱怨一下的是,Shark源码里面,虽然把整套内核提炼出一个纯接口工程,写在SharkAPI模块中,同时提供整套实现该接口的实现类,这样是为了用户可以根据自己的需要,可以灵活的重写一些模块来完成Shark官方未支持的功能。想法不错,但是在各个实现类中,很多方法内部都把接到的Interface类型参数转型成具体Implements Class类型来处理,这样导致调用者和具体实现者里面的这个参数必须是同一个实现类产生的,不然就会出现ClassCastException,这样的直接影响是如果要将DODS换成Hibernate,一换就必须把十几个模块的持久层实现全部换掉,不能一部分使用DODS,一部分使用Hibernate,所以要一次完成的改动的代码量就变得很大,增加调试难度。其实如果一定要做还是可以的,代码里面转型的参数大部分是UserTranaction类型,忽略掉直接提交就是了,当然,这样会导致事务不统一,玩玩可以,实际系统是不能用的。感觉Shark这部分代码考虑的不够完善。

    4.替换Hibernate遇到第一个问题就是无论Shark1.0、1.1还是1.x版中最后的1.1.2中所带的Hibernate实现都是针对Shark1.0的,或者说,里面的Hibernate实现在1.0之后就没人升级维护过。在Shark ReleaseNote里面写道一句这样的话:Contributed Hibernate layers similar to DODS layers for all APIs that have such DODS layers (more than 10 layers). Unfortunatelly, these layers are not worked out completely, and there is nobady to maintain them (especially InstancePersistence layer), and are included only as a source code. 够faint的-_-#,这十来个要替换的模块里面大部分是缺少实现接口中方法,有的是后来接口增加了方法(如它自己提到的“InstancePersistence layer”,就是负责流程实例表、活动实例表、分配表读写数据库最频繁的一个模块,有18个方法没有实现,都是1.0之后加的),有的是实现类实现的接口都不存在了,或者改了另外一个(如SharkTransaction模块中,Hibernate是实现了SharkTransaction接口,DODS则实现了SharkInternalTransaction接口,后者继承前者的,增加了几个方法),所以除非用的是Shark1.0(似乎大部分用的都是1.1.2了)指望更改几个设置,或者少量代码就切换过来是不可能的。就算是依葫芦画瓢,也得照着DODS的实现,把Hibernate里面该改的代码改了,该加的代码加上才行。全部要该的地方有两三千行,全部写出来不现实,就不写了。

    5.下一个遇到的困难是Hibernate实现有少许逻辑跟DODS实现不一样,譬如验证模块(Authentication Layer)中,判断用户名密码是否匹配,DODS是将密码进行SHA-1加密后进行比较的,Hibernate则是直接用密码明文跟数据库中的信息进行比较(预留了passwordDigest方法进行加密,该方法直接返回传入的Password参数),很明显,两者不能直接通用。幸好,这样的地方不多,而且通常一两句代码就能修正过来。

    6.替换Hibernate遇到的最大的麻烦是Hibernate与DODS使用数据结构的不一致,这也是Shark1.0和1.1版本历史差异造成的。最显而易见不一致就是“oid”:1.1版本中,DODS会用到一个ObjectID表,并将大多数表里面增加一个oid字段作为该表的主键,而Hibernate实现自然是根据1.0的数据结构,完全不使用到oid的,这样一来主键和外键都发生了变化。另外在同一个表里面的字段的意义也发生了变化,譬如grouptable里面的groupid字段,DODS认为是存储组名称的,而Hibernate认为是一个非自然主键(既DODS中OID的作用),所以如果之前有使用DODS做了一些数据,中途改为Hibernate后,就会报“将数据类型 varchar 转换为 numeric 时出错”,更不用说1.1相对1.0所增加的12张表和原有表中增加的一些字段了。要改变Hibernate中的hbm.xml、POJO以及内部访问代码的逻辑,才能兼容回1.1的数据结构。
 
 
 

Shark的用户管理模块是独立于其它模块的,为了方便与其它系统整合,可以把该模块改为Hibernate实现。

Shark中附带的Hibernate实现代码是针对Shark 1.0版本的,在当前的版本(1.1-2)中,数据库的结构和SharkAPI都发生了变化,所以要对Hibernate代码和数据库做一些调整。

另外,Shark中附带的Hibernate实现代码是Hibernate 2.0的,如果需要,做一些很小的调整就可以升级到Hibernate 3.0

Hibernate代码的调整完全可以依赖SharkAPI说明来做,由于数据库主键都发生了变化,所有查询都需要更改。但是由于Shark的查询方式非常单一,例如对用户表只有一种查询方式,对group表也只有一种查询方式,改动可以很快完成。

Shark用户模块的数据库只有4个表,分别是GroupTableGroupGroupTableUserGroupTableUserTableShark数据库的主要修改在于主键发生了变化。由于DODS的需要,每个表都有OIDVersion两个列,其中OID是主键。因此,主要问题就集中在这两个字段如何赋值。如果采用的是其它系统的用户表就没有这个问题了。

以下三个文件是Hibernate的配置文件:

hibernate.user.cfg.xml

HibernateUser.hbm.xml

HibernateGroup.hbm.xml

放置在{classes}/hbm/UserGroup/目录下,

org.enhydra.shark.usertransaction.ThreadLocalSession文件中需要指出配置文件的路径:

   static {

      try {

         sessionFactory = new Configuration().configure(

            "/hbm/UserGroup/hibernate.user.cfg.xml").buildSessionFactory();

      } catch (HibernateException ex) {

         throw new RootError("Exception building SessionFactory: "

                                + ex.getMessage(), ex);

      }

   }

 

shark.conf需要做如下调整:

首先,更换AuthenticationManager接口的实现类,选用HibernateAuthenticationManager

#AuthenticationManagerClassName=org.enhydra.shark.authentication.LDAPAuthenticationManager

#AuthenticationManagerClassName=org.enhydra.shark.authentication.DODSAuthenticationManager

AuthenticationManagerClassName=org.enhydra.shark.authentication.HibernateAuthenticationManager

其次,更换UserGroupManager接口的实现类,选用HibernateUserGroupManager

#UserGroupManagerClassName=org.enhydra.shark.usergroup.LDAPUserGroupManager

#UserGroupManagerClassName=org.enhydra.shark.usergroup.DODSUserGroupManager

UserGroupManagerClassName=org.enhydra.shark.usergroup.HibernateUserGroupManager

第三,更换UserTransactionManager接口的实现类,选择HibernateUserTransactionFactory

#UserTransactionManagerClassName=org.enhydra.shark.usertransaction.DODSUserTransactionFactory

UserTransactionManagerClassName=org.enhydra.shark.usertransaction.HibernateUserTransactionFactory

总之,用户管理模块改为Hibrnate实现的工作量不大。

原创粉丝点击