2012-01-13 17 views
7

Kiedyś wszystkie moje DAO rozszerzały klasę JdoDaoSupport, która jest teraz deprecated in Spring 3.1. Zrobiłem własną klasę AbstractJdoDao, która owija PersistenceManagerFactory i wszystkie DAO rozszerzają się od tego miejsca. Czy tak powinienem robić?Konfigurowanie JDO na wiosnę 3.1?

Również w documentation on JDO, wydaje się, że bezpośrednie instancji od PersistenceManagerFactory nie jest to opcja domyślna, ale używać LocalPersistenceManagerFactoryBean zawinięte w TransactionAwarePersistenceManagerFactoryProxy. Jak prawidłowo utworzyć te ziarna i sprawić, by działały z adnotacjami ze Springa @Transactional.

Oto część związana wytrwałość-mojego kontekstu aplikacji:

<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> 

Teraz gdy załadować stronę dostępu do magazynu danych:

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 

ja mam my example project on GitHub. Korzysta z Google App Engine, więc uruchom go przez mvn gae:run w Eclipse (z wtyczką Google for Eclipse), najpierw tworząc projekt Eclipse przez mvn eclipse:eclipse.

+0

Czytając dokumentację stwierdzam, że właściwość "persistenceManagerFactory" komponentu bean "transactionManager" powinna odwoływać się do komponentu bean "LocalPersistenceManagerFactoryBean" zamiast do proxy. Musisz nadać tej komórce identyfikator, zamiast być anonimowym, jak w twoim przykładzie. – Luciano

Odpowiedz

3

Moja sugestia to użycie TransactionAwarePersistenceManagerFactoryProxy lub SpringPersistenceManagerProxyBean zgodnie z sugestią zawartą w dokumentacji Spring 3.1. Wygląda na to, że ma to na celu zastąpienie klasy JdoDaoSupport.

To, co sugerujesz w swoim pytaniu o stworzenie własnego opakowania AbstractJdoDao, oczywiście wyeliminuje ostrzeżenie o wycofaniu, moim jedynym zmartwieniem jest to, że możesz przypadkowo stworzyć sytuację, która jest trudna do utrzymania dla innych, ponieważ nie będzie do czego są przyzwyczajeni.

Z drugiej strony, wyobrażam sobie tworzenia własnych wrapper jest bardzo szybkim sposobem na rozwiązanie problemu ...

Należy starannie rozważyć zalety/wady korzystania z własnego opakowania z zalet/wad posuwając się naprzód ze sposobem działania Spring 3.1. Z mojego doświadczenia wynika, że ​​branie na skróty może i często powraca, by prześladować Cię w przyszłości.

+0

Czy 'AbstractJdoDao' powinien raczej mieć odniesienie do' TransactionAwarePersistenceManagerFactoryProxy' niż 'PersistenceManagerFactory'? – hleinone

+0

Tak, masz rację. Przykłady, których używają w [Spring 3.1 JDO documentation] (http://static.springsource.org/spring/docs/3.1.0.RC1/spring-framework-reference/html/orm.html#orm-jdo -daos-straight) pokaż PersistenceManagerFactory wprowadzony do twojej klasy Dao za pomocą obiektu TransactionAwarePersistenceManagerFactoryProxy. Sądzę, że mógłbyś wprowadzić to w abstrakcyjną klasę i odziedziczyć po niej to samo; jednak nie używają klasy abstrakcyjnej w przykładach. Według dokumentów zaletą tej metody jest to, że nie używasz żadnych zależności Spring. – jmort253

+0

Odizolowałem problem w [projekcie na GitHubie] (https://github.com/hleinone/spring-gae-jdo). Nadal kończy się prawie tym samym wyjątkiem. – hleinone