在theServerSide.com上有一些人声称JDO的开发人员已经把JDO带向错误的道路,并且指出Hibernate相对更优秀。然而,根据我的经验Hibernate和JDO都是O/R Mapping的优秀技术。
它们有许多共同的特征,包括: 
- 
支持Plain Old Java Object (POJO) 的几近透明的持久层 
 - 
基於XML的object/relational映射 
 - 
两者都有一个"EntityManager" API - Hibernate Session 和 JDO PersistenceManager 
 - 
都可以在或不在Container中运行应用程序 
 - 
事务级和应用级的cache 
 - 
丰富的查询语言 (query language) 
 - 
能够积极和消极两种方式装载有关联的对象 
 - 
有效率地处理大数据集合   
因此,JDO 和 Hibernate 两种版本的同一应用程序经常很相似。  
关于如何装载对象和执行查询,我们来看看下面的例子。这里有两个版本的RestaurantRepository类,一个是JDO的,另一个是Hibernate的。 RestaurantRepository类定义了寻找饭店的方法: 
列表 1 显示了JDO版的 RestaurantRepository 类, 列表 2 显示了Hibernate 的版本。  
列表 1 - JDO 版 
public class JDORestaurantRepositoryImpl     implements RestaurantRepositoryImpl { 
  public Restaurant findRestaurant(String restaurantId) {    PersistenceManager pm = PMRegistry.getPM();    return (Restaurant) pm.getObjectById(     pm.newObjectIdInstance(      JDORestaurant.class,      restaurantId),     true);   } 
     private static final String QUERY_STRING =         "serviceArea.contains(zipCode) && timeRanges.contains(tr) && "             + "(tr.dayOfWeek == day && "             + "(tr.openHour < hour || (tr.openHour == hour && tr.openMinute <= minute)) && "             + "(tr.closeHour > hour || (tr.closeHour == hour && tr.closeMinute > minute)))"; 
    public Collection findRestaurants(         Address deliveryAddress,         Date deliveryTime) {         Calendar c = Calendar.getInstance();         c.setTime(deliveryTime);         int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);         int hour = c.get(Calendar.HOUR_OF_DAY);         int minute = c.get(Calendar.MINUTE); 
        PersistenceManager pm = PMRegistry.getPM();         Query query = pm.newQuery(JDORestaurant.class, QUERY_STRING);         query.declareVariables("JDOTimeRange tr");         query.declareParameters(             "String zipCode, int day, int hour, int minute");         Collection result =             (Collection) query.executeWithArray(                 new Object[] {                     deliveryAddress.getZip(),                     new Integer(dayOfWeek),                     new Integer(hour),                     new Integer(minute)});         return result;     } } 
  
列表 2 - Hibernate 版 
public class HibernateRestaurantRepositoryImpl     implements RestaurantRepositoryImpl { 
    public Restaurant findRestaurant(String restaurantId) {         try {             Session session = HibernateSessionRegistry.getSession();             Restaurant restaurant =                 (Restaurant) session.load(                     HibernateRestaurant.class,                     new Long(restaurantId));             return restaurant;         } catch (HibernateException e) {             throw new ApplicationRuntimeException(e);         }     } 
    public Collection findRestaurants(         Address deliveryAddress,         Date deliveryTime) {         try {             Query query =                 makeFindRestaurantsQuery(                     deliveryAddress,                     deliveryTime);             return query.list();         } catch (HibernateException e) {             throw new ApplicationRuntimeException(e);         }     } 
    private Query makeFindRestaurantsQuery(         Address deliveryAddress,         Date deliveryTime)         throws HibernateException {         Calendar c = Calendar.getInstance();         c.setTime(deliveryTime);         int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);         int hour = c.get(Calendar.HOUR_OF_DAY);         int minute = c.get(Calendar.MINUTE);         Session session = HibernateSessionRegistry.getSession();         Query query =             session.getNamedQuery("findAvailableRestaurants");         query.setString("zipCode", deliveryAddress.getZip());         query.setInteger("dayOfWeek", dayOfWeek);         query.setInteger("hour", hour);         query.setInteger("minute", minute);         query.setCacheable(true);         return query;     } } 
每个 repository 由两个方法组成。这两个方法调用相应的 persistence framework API: 
- 
findRestaurant() - JDO 版调用 PersistenceManager.getObjectById() 而 Hibernate版调用 Session.load() 
 - 
findAvailableRestaurants() - 两个版本都使用Query interface来执行有名参数的查询. 有个不同的地方,Hibernate 版用 named query, named query会在一个映射文件中定义,而 JDO 版用镶嵌在类里的 query    
两个类通过 ThreadLocal-based registry 得到 Hibernate Session 和 JDO PersistenceManager。如你所见,除了方法和类的名字不同,其它code都非常相似。  
 
  |