Spring支持标准的JDO 1.0/2.0 API作为数据访问策略,同样遵循类似于Spring对Hibernate的支持风格。对应的支持与整合类位于 org.springframework.orm.jdo 包中。
Spring提供了一个 LocalPersistenceManagerFactoryBean 类,允许你通过Spring的application context来定义一个本地的JDO PersistenceManagerFactory:
      
<beans>
  <bean id="myPmf" class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
    <property name="configLocation" value="classpath:kodo.properties"/>
  </bean>
</beans>
作为可选方案,PersistenceManagerFactory 也可以通过直接实例化一个 PersistenceManagerFactory 的实现类得到。
		一个JDO PersistenceManagerFactory 的实现类遵循JavaBeans的模式,它非常像一个JDBC DataSource 的实现类,这使得它天然的非常适合作为一个Spring的bean定义。
		这种创建风格通常支持一个Spring定义的JDBC DataSource,将它传入到对应的实现类的connectionFactory的属性中进行bean的创建。具体的例子参见开源的JDO实现JPOX(http://www.jpox.org):
<beans>
 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
   <property name="driverClassName" value="${jdbc.driverClassName}"/>
   <property name="url" value="${jdbc.url}"/>
   <property name="username" value="${jdbc.username}"/>
   <property name="password" value="${jdbc.password}"/>
 </bean>
 <bean id="myPmf" class="org.jpox.PersistenceManagerFactoryImpl" destroy-method="close">
   <property name="connectionFactory" ref="dataSource"/>
   <property name="nontransactionalRead" value="true"/>
 </bean>
</beans>
一个JDO的 PersistenceManagerFactory 能够同样在一个J2EE应用服务器的JNDI环境下被创建。
		这通常由特定的JDO实现所提供的JCA连接器来完成。Spring标准的 JndiObjectFactoryBean 也能够被用来获取和暴露这个 PersistenceManagerFactory。
		当然,通常在一个EJB环境之外,在JNDI中持有 PersistenceManagerFactory 的实例没有什么特别吸引人的好处,因而我们一般只在有非常充足的理由时选择这种建立方式。
		请参看Hibernate章节中“容器资源 vs 本地资源”这一节的讨论,那里的讨论同样适用于JDO。
      
       每一个基于JDO的DAO类都需要通过IoC来注入一个 
      PersistenceManagerFactory。
			这样的DAO类可以在 PersistenceManagerFactory 的帮助下来操作原生的JDO API进行编程,
			但是通常来说我们更愿意使用Spring提供的 JdoTemplate:
      
<beans>
  
  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmf"/>
  </bean>
  
</beans>
public class ProductDaoImpl implements ProductDao {
  
    private JdoTemplate jdoTemplate;
    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
        this.jdoTemplate = new JdoTemplate(pmf);
    }
    public Collection loadProductsByCategory(final String category) throws DataAccessException {
        return (Collection) this.jdoTemplate.execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                Query query = pm.newQuery(Product.class, "category = pCategory");
                query.declareParameters("String pCategory"); 
                List result = query.execute(category);
                // do some further stuff with the result list
                return result;
            }
        });
    }
}
       一个回调的实现能够有效地在任何JDO数据访问中使用。
      JdoTemplate 会确保当前的 PersistenceManager 
       对象的正确打开和关闭,并自动参与到事务管理中去。
		  Template实例不仅是线程安全的,同时它也是可重用的,因而他们可以作为外部对象的实例变量而被持有。
		  对于那些简单的诸如 find、load、
		  makePersistent 或者 delete 操作的调用,
		  JdoTemplate 提供可选择的快捷函数来替换这种回调的实现。
		  不仅如此,Spring还提供了一个简便的 JdoDaoSupport 基类,
		  这个类提供了 setPersistenceManagerFactory(..) 方法来接受一个 
		  PersistenceManagerFactory 对象,
		  同时提供了 getPersistenceManagerFactory() 
		  和 getJdoTemplate() 给子类使用。
		  综合了这些,对于那些典型的业务需求,就有了一个非常简单的DAO实现:
      
public class ProductDaoImpl extends JdoDaoSupport implements ProductDao {
  
    public Collection loadProductsByCategory(String category) throws DataAccessException {
        return getJdoTemplate().find(
            Product.class, "category = pCategory", "String category", new Object[] {category});
    }
}
作为不使用Spring的 JdoTemplate 来实现DAO的替代解决方案,你依然可以通过在原生JDO API的级别对那些基于Spring的DAO进行编程,此时你必须明确地打开和关闭一个 PersistenceManager。
		正如在相应的Hibernate章节描述的一样,这种做法的主要优点在于你的数据访问代码可以在整个过程中抛出checked exceptions。JdoDaoSupport 为这种情况提供了多种函数支持,
		包括获取和释放一个具备事务管理功能的 PersistenceManager 和相关的异常转化。
我们可以直接操作JDO API来实现DAO,通过直接使用一个注入的 PersistenceManagerFactory,而无需对Spring产生的任何依赖。
		一个相应的DAO实现看上去就像下面这样:
public class ProductDaoImpl implements ProductDao {
    private PersistenceManagerFactory persistenceManagerFactory;
    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
        this.persistenceManagerFactory = pmf;
    }
    public Collection loadProductsByCategory(String category) {
        PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
        try {
            Query query = pm.newQuery(Product.class, "category = pCategory");
            query.declareParameters("String pCategory"); 
            return query.execute(category);
        }
        finally {
          pm.close();
        }
    }
}
      
      上面我们所列出的DAO完全遵循IoC,它如同使用Spring的 
      JdoTemplate 进行编码那样,非常适合在Spring容器中进行配置:
      
<beans>
  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmf"/>
  </bean>
</beans>
这类DAO的主要问题在于他们每次总是从工厂中得到一个新的 PersistenceManager 
       实例。为了依然能够访问受到Spring管理的、具备事务管理功能的 PersistenceManager,
       不妨考虑一下在目标 PersistenceManagerFactory 之前,
			定义一个 TransactionAwarePersistenceManagerFactoryProxy(Spring已经提供),
			然后将这个代理注入到你的DAO中去。
      
<beans>
  <bean id="myPmfProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory" ref="myPmf"/>
  </bean>
  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmfProxy"/>
  </bean>
</beans>
      	这样,你的数据访问代码就可以通过 PersistenceManagerFactory.getPersistenceManager() 
       	方法得到一个具备事务管理功能的 PersistenceManager。
				而这一方法将通过代理类的处理:在从工厂获取一个新的 PersistenceManager 
				实例之前检查一下当前具备事务管理功能的 PersistenceManager,
				如果这是一个具备事务管理功能的 PersistenceManager,
				close() 调用在此时将被忽略。
      
      	如果你的数据访问代码总是在一个处于活跃状态的事务中执行(或者至少在一个活跃的事务同步中),
      	那么你能够非常安全地忽略 PersistenceManager.close() 的调用和整个 
      	finally 块的代码。这将使你的DAO实现变得比较简洁:
      
public class ProductDaoImpl implements ProductDao {
    private PersistenceManagerFactory persistenceManagerFactory;
    public void setPersistenceManagerFactory(PersistenceManagerFactory pmf) {
        this.persistenceManagerFactory = pmf;
    }
    public Collection loadProductsByCategory(String category) {
        PersistenceManager pm = this.persistenceManagerFactory.getPersistenceManager();
        Query query = pm.newQuery(Product.class, "category = pCategory");
        query.declareParameters("String pCategory"); 
        return query.execute(category);
    }
}
对于这种依赖于活跃事务的DAO,比较推荐的做法是将 
      TransactionAwarePersistenceManagerFactoryProxy 
      中的"allowCreate"标志关闭,从而强制活跃事务。
<beans>
  <bean id="myPmfProxy"
      class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory" ref="myPmf"/>
    <property name="allowCreate" value="false"/>
  </bean>
  <bean id="myProductDao" class="product.ProductDaoImpl">
    <property name="persistenceManagerFactory" ref="myPmfProxy"/>
  </bean>
</beans>
这种DAO访问方式的主要优势在于它仅仅依赖于JDO API本身而无需引入任何的Spring的类。 从无入侵性的角度来看,这一点非常吸引人。同时,对于JDO开发人员来说也更自然。
      	然而,这样的DAO访问方式会抛出 JDOException,
      	这是一个无需声明或捕获的unchecked exception。这意味着,DAO的调用者只能以普通的错误来处理这些异常,
      	除非完全依赖JDO自身的异常体系。因而,除非你将DAO的调用者绑定到具体的实现策略上去,
      	否则你将无法捕获特定的异常原因(诸如乐观锁异常)。这种折中平衡或许可以被接受,
      	如果你的应用完全基于JDO或者无需进行特殊的异常处理。
      
      	总体来说,DAO可以基于JDO的原生API实现,同时,它依旧需要能够参与到Spring的事务管理中。
			这对于那些已经对JDO非常熟悉的人来说很有吸引力,因为这种方式更加自然。
			不过,这种DAO将抛出 JDOException,因而,
			如果有必要的话需要明确地去做由 JDOException 到Spring的 
			DataAccessException 的转化。
      
将事务管理纳入到Service操作的执行中,你可以使用Spring通用的声明式的事务管理功能, 参加下面的例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
  <bean id="myTxManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    <property name="persistenceManagerFactory" ref="myPmf"/>
  </bean>
  <bean id="myProductService" class="product.ProductServiceImpl">
    <property name="productDao" ref="myProductDao"/>
  </bean>
  <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
      <tx:method name="increasePrice*" propagation="REQUIRED"/>
      <tx:method name="someOtherBusinessMethod" propagation="REQUIRES_NEW"/>
      <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
    </tx:attributes>
  </tx:advice>
  <aop:config>
    <aop:pointcut id="productServiceMethods" expression="execution(* product.ProductService.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="productServiceMethods"/>
  </aop:config>
</beans>
注意,JDO要求你必须在一个活跃的事务中修改一个持久化对象。
       与Hibernate相比,在JDO中并没有一种类似脱离事务刷出(non-transactional flush)的概念。
			基于这种原因,你所选择的JDO实现需要被建立在特定的环境中,尤其是它需要为JTA同步做明确的创建,
			由此来自行检测一个JTA事务。这一点对于本地事务不是必要的,由于它已经被Spring的 
			JdoTransactionManager 处理,但是对于需要参与到JTA事务中的情况,是必须的
			(无论是由Spring的 JtaTransactionManager、EJB CMT或者普通的JTA所驱动的事务)。
			
      	JdoTransactionManager 能够将一个JDO事务暴露给访问相同的JDBC 
      	DataSource 的JDBC访问代码。前提条件是,被注册的 
      	JdoDialect 能够支持获取底层的JDBC Connection。
				这一功能默认被基于JDBC的JDO 2.0 实现。对于JDO 1.0的实现,必须注册一个用户自定义的 
				JdoDialect。具体参见下一节有关 JdoDialect 的机制。
      
      	作为高级特性,JdoTemplate 和 interfacename 
      	都支持一个用户自定义的 JdoDialect 作为“jdoDialect”的bean属性进行注入。
				在这种情况下,DAO将不再接收 PersistenceManagerFactory 的引用作为参数,
				而是接收一个完整的 JdoTemplate 实例(也就是将它注入到 
				JdoDaoSupport 的"jdoTemplate"属性中去)。一个 JdoDialect 
				实现能够激活一些由Spring支持的高级特性,这通常由特定的实现供应商指定:
      
执行特定的事务语义(例如用户自定义的事务隔离级别和事务超时)
获取具备事务功能的JDBC Connection (暴露给基于JDBC的DAO)
应用查询超时功能(自动地从Spring管理的事务超时中计算)
及时刷出 PersistenceManager (使得事务变化对于基于JDBC的数据访问代码可见)
从 JDOExceptions 到Spring的 DataAccessExceptions 的高级转化
这对于JDO 1.0的实现有特别的价值,由于这些特性都没有在其标准的API中包含。
			对于JDO 2.0,其中的绝大多数的特性已经以标准的方式被支持。因而,Spring的 DefaultJdoDialect 
			在默认情况下(Spring 1.2后)使用相应的JDO 2.0 API函数。对于特殊的事务语义和异常的高级转化这样的高级特性,
			获取和使用JDO实现供应商特定的 JdoDialect 子类还是比较有价值的。
			
更多有关它的操作以及它如何在Spring的JDO支持中使用的详细信息请参看
       JdoDialect 的Javadoc。