在公司组建virtual团队之 关于持久层

在公司组建virtual团队之 关于持久层

链接 在公司组建virtual团队(一) 在公司组建virtual团队(二) 大家都说没有绝对好的技术框架,只有适合的。我觉得如果非要考量一种技术框架好坏,可以从两个方面看,一看是否帮助程序员productive,二看是否灵活,适合实现细粒度的功能。通常这两个方面互相矛盾。就好象NBA里力量和速度是两个重要的身体素质指标。但是力量越好的,往往速度越差。NBA里最NB的往往是这两方面协调的比较好的,比如很多人力量比小皇帝詹姆斯好,也有很多人速度比他快。但力量比他大的,速度都不如他;速度比他快的力量肯定比他差远了。这就是一个天赋球员。

持久层可以用spring JDBC template, iBatis, Hibernate,当然还有很多我不了解的。哦,别忘了还有ROO, 它也包含持久层的实现,或者说,是很酷地封装了其他框架的实现。

对我来说,足够productive的,只有Hibernate和ROO。跑了一遍ROO的PizzaShop的例子,真是太酷了。以前在Oracle的时候用过一个支持快速开发的产品叫Html DB,也很棒,但是ROO更透明,也更优雅。ROO主要基于annotation和aspectj。生成一个简单的应用,只用10条左右的命令。从理论上说,ROO也适合控制细粒度的功能,可惜我不熟aspectJ以及它所采用的前端的技术,犹豫了一下还是觉得走这条路风险太大。但我非常看好ROO的发展,以后有时间要好好研究一下。喜欢ROO的另一个原因是,它生成的是Rich Model, 即使使用Hibernate.

Hiberante也是我很喜欢的技术,两个原因,一是喜欢它transparent persistence的定位。二是它强调fine grained class,合俺胃口。Gavin在他的Hibernate书里(书可以从分享十二本经典电子书这篇里找到)介绍了基于Hibernate做持久层的一个思路,很棒,如果说更具体的代码实现,可以看SpringSide2。事实上很多人现在都在采用这种方式封装持久层。

Spring提供了HibernateDaoSupport类对Hibernate支持,DAO类继承了这个类之后,可以方便地得到HiberanteTemplate, 它的好处在于封装了对session的管理,另外它也参与集成了对transaction的管理。SpringSide2主要基于HibernateDaoSupport和一些其他的技巧,实现了很薄的DAO层,基本上薄到没有DAO层了。

   1: @Service
   2: public class BoardManager extends HibernateEntityDao<Board>{
   3: }

上面这么一个空manager类,里面已经包含关于Board类的CRUD的功能了,Board类是映射数据库的一个贫血实体类。

我几乎没有改SpringSide2对于Hibernate的封装,改动只包含两种:一种是把eclipse报warning给@SuppressWarnings(“unchecked”)掉了 另一种是把中文注释翻译成英文了。涉及到的java类在博客的最后有下载链接

我们具体看看是怎么做到的。

先写个DAO的基类,叫做HibernateGenericDao。这个类对泛型或Object类封装了CRUD的操作,以保证不依赖某个具体的实体类,看具体例子就能明白大体是怎么回事了

   1: public <T> T get(Class<T> entityClass, Serializable id) {
   2:     return (T) getHibernateTemplate().load(entityClass, id);
   3: }
   4:  
   5: public void remove(Object o) {
   6:     getHibernateTemplate().delete(o);
   7: }
   8:  
   9: public <T> void removeById(Class<T> entityClass, Serializable id) {
  10:     remove(get(entityClass, id));
  11: }

这个类还有一个有技巧的地方在于:

   1: public <T> List<T> getAll(Class<T> entityClass, String orderBy, boolean isAsc) {
   2:     Assert.hasText(orderBy);
   3:     if (isAsc)
   4:         return getHibernateTemplate().findByCriteria(
   5:                 DetachedCriteria.forClass(entityClass).addOrder(Order.asc(orderBy)));
   6:     else
   7:         return getHibernateTemplate().findByCriteria(
   8:                 DetachedCriteria.forClass(entityClass).addOrder(Order.desc(orderBy)));
   9: }

这里使用了DetachedCriteria. DetachedCriteria和Criteria有共同的父类。两者的区别在于Criteria是在线的,而DetachedCreteria是离线的,也就是没有session. 这样正好可以用HibernateTemplate的session.

继续… 再写一个子类:

   1: public class HibernateEntityDao<T> extends HibernateGenericDao

在子类中,终于把泛型去掉了,举例:

   1: protected Class<T> entityClass;// entity type that DAO manages
   2:  
   3: public HibernateEntityDao() {
   4:     entityClass = GenericsUtils.getSuperClassGenricType(getClass());
   5: }
   6:  
   7: protected Class<T> getEntityClass() {
   8:     return entityClass;
   9: }
  10:  
  11: public T get(Serializable id) {
  12:     return get(getEntityClass(), id);
  13: }

这里的关键在于GenericsUtils.getSuperClassGenericType(getClass())

最终调用到的code是:

   1: public static Class getSuperClassGenricType(Class clazz, int index) {
   2:  
   3:     Type genType = clazz.getGenericSuperclass();
   4:  
   5:     if (!(genType instanceof ParameterizedType)) {
   6:         log.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
   7:         return Object.class;
   8:     }
   9:  
  10:     Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  11:  
  12:     if (index >= params.length || index < 0) {
  13:         log.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
  14:                 + params.length);
  15:         return Object.class;
  16:     }
  17:     if (!(params[index] instanceof Class)) {
  18:         log.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
  19:         return Object.class;
  20:     }
  21:     return (Class) params[index];
  22: }

略作说明:

传进来的参数是org.emoticon.forum.manager.BoardManager

genType是org.emoticon.core.persistence.HibernateEntityDao<org.emoticon.forum.model.Board>

返回值是Board.

通过这种方式,就实现了之前说的:

 

   1: public class RoleManager extends HibernateEntityDao<Role> {
   2:  
   3: }

空manager类自动获得CRUD的功能

具体代码可以从这里下载:

http://cid-d8b11f9bf86fecfa.office.live.com/self.aspx/.Public/code/HibernateWrapper.zip

你可能感兴趣的:(在公司组建virtual团队之 关于持久层)