在 Spring 3.1 中配置 JDO?

Posted

技术标签:

【中文标题】在 Spring 3.1 中配置 JDO?【英文标题】:Configuring JDO in Spring 3.1? 【发布时间】:2012-02-09 19:23:06 【问题描述】:

我曾经让我的所有 DAO 扩展 JdoDaoSupport 类,现在是 deprecated in Spring 3.1。我创建了自己的 AbstractJdoDao 类,它包装了 PersistenceManagerFactory,所有的 DAO 都从那里扩展。我应该这样做吗?

同样在documentation on JDO中,似乎PersistenceManagerFactory的直接实例化不是默认选项,而是使用LocalPersistenceManagerFactoryBean包裹在TransactionAwarePersistenceManagerFactoryProxy中。如何正确实例化这些 bean 并使它们与 Spring 的 @Transactional 注释一起工作。

这是我的应用程序上下文中与持久性相关的部分:

<bean id="persistenceManagerFactoryProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
    <property name="targetPersistenceManagerFactory">
        <bean class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
            <property name="jdoPropertyMap">
                <props>
                    <prop key="javax.jdo.PersistenceManagerFactoryClass">org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory</prop>
                    <prop key="javax.jdo.option.ConnectionURL">appengine</prop>
                    <prop key="javax.jdo.option.NontransactionalRead">true</prop>
                    <prop key="javax.jdo.option.NontransactionalWrite">false</prop>
                    <prop key="javax.jdo.option.RetainValues">false</prop>
                    <prop key="javax.jdo.option.DetachAllOnCommit">true</prop>
                    <prop key="javax.jdo.option.Multithreaded">true</prop>
                    <prop key="datanucleus.appengine.ignorableMetaDataBehavior">NONE</prop>
                </props>
            </property>
        </bean>
    </property>
    <property name="allowCreate" value="false" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
    <property name="persistenceManagerFactory" ref="persistenceManagerFactoryProxy" />
</bean>

现在当我加载访问数据存储的页面时:

org.springframework.transaction.CannotCreateTransactionException: Could not open JDO PersistenceManager for transaction; nested exception is java.lang.IllegalStateException: No JDO PersistenceManager bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.jdo.JdoTransactionManager.doBegin(JdoTransactionManager.java:369) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371) ~[spring-tx-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:335) ~[spring-tx-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105) ~[spring-tx-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[spring-aop-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) ~[spring-aop-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at $Proxy15.queryAll(Unknown Source) ~[na:na]
    ...
Caused by: java.lang.IllegalStateException: No JDO PersistenceManager bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.jdo.PersistenceManagerFactoryUtils.doGetPersistenceManager(PersistenceManagerFactoryUtils.java:153) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy$PersistenceManagerFactoryInvocationHandler.invoke(TransactionAwarePersistenceManagerFactoryProxy.java:159) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
    at $Proxy13.getPersistenceManager(Unknown Source) ~[na:na]
    at org.springframework.orm.jdo.JdoTransactionManager.doBegin(JdoTransactionManager.java:308) ~[spring-orm-3.1.0.RELEASE.jar:3.1.0.RELEASE]
... 73 common frames omitted

我有my example project on GitHub。它使用 Google App Engine,所以要么在 Eclipse 中通过 mvn gae:run 运行它(使用 Google Plugin for Eclipse),首先通过 mvn eclipse:eclipse 创建一个 Eclipse 项目。

【问题讨论】:

阅读文档,我得出结论,bean“transactionManager”的属性“persistenceManagerFactory”应该引用bean“LocalPersistenceManagerFactoryBean”而不是代理。所以你需要给那个bean一个id,而不是像你的例子那样匿名。 【参考方案1】:

我的建议是按照 Spring 3.1 文档的建议使用 TransactionAwarePersistenceManagerFactoryProxySpringPersistenceManagerProxyBean。看来这是为了替代 JdoDaoSupport 类。

虽然您在创建自己的 AbstractJdoDao 包装器的问题中所建议的内容当然会消除弃用警告,但我唯一担心的是您可能会无意中造成其他人难以维持的情况,因为它不会成为他们习惯看到的样子。

另一方面,我认为创建自己的包装器是解决问题的一种非常快速的方法......

您应该仔细权衡使用自己的包装器的优点/缺点和使用 Spring 3.1 做事方式的优点/缺点。根据我的经验,走捷径可能会而且经常会在未来再次困扰您。

【讨论】:

应该 AbstractJdoDao 然后而不是引用 TransactionAwarePersistenceManagerFactoryProxy 而不是 PersistenceManagerFactory 是的,你是对的。他们在Spring 3.1 JDO documentation 中使用的示例显示了使用 TransactionAwarePersistenceManagerFactoryProxy 对象将 PersistenceManagerFactory 注入到您的 Dao 类中。我想你可以将它注入一个抽象类并从它继承;但是,他们在示例中没有使用抽象类。根据文档,这种方法的优点是您没有使用任何 Spring 依赖项。 我将问题隔离到project on GitHub。仍然以几乎相同的异常结束。 我现在已经解决了示例项目中的问题。最后主要是配置错误,但你的回答确实帮助我解决了这个问题。 很高兴我能提供帮助!感谢您的反馈:)

以上是关于在 Spring 3.1 中配置 JDO?的主要内容,如果未能解决你的问题,请参考以下文章

spring,mybatis事务管理配置与@Transactional注解使用[转]

如何通过属性文件而不是通过 env 变量或系统属性设置活动 spring 3.1 环境配置文件

WebApplicationInitializer究 Spring 3.1之无web.xml式 基于代码配置的servlet3.0应用

无法使用具有正确凭据的 Spring 3.1 验证 LDAP 帐户

Spring开发2 spring基础及组件使用2(conditional,import,factorybean)

App Engine、JDO 和 Maven。启动时出错