Datanucleus:从 @Transactional 转向非事务性

发布于 2024-12-03 19:11:33 字数 1886 浏览 1 评论 0原文

我正在使用 Datanucleus、JDO 和 Spring 与 Aspect-J 交织的声明式 @Transactional 管理。

但是,当“普通”方法从 @Transactional 方法获取持久对象时,该对象的状态将变为瞬态(持久管理器似乎已被删除)并且该对象不再是持久的。

示例:

public class Example {

    public void test() throws Exception {
       Login l = getLogin();                          
       JDOHelper.getObjectState(l);              // transient instead of persistent
       l.getSomeOtherPersistentObj().doStuff();  // NullpointerException :(
    }

    @Transactional
    private Login getLogin() {
        // do transactional stuff here
        // ..
        return dao.find(Login.class, 1);
    }
}

这是为什么?如何在不需要事务的地方添加 @Transactional 的情况下修复它?以下确实(显然)有效,因此这表明可以建立事务性连接和非事务性连接:

  • @Transactional 方法调用 @Transactional 方法
  • @Transactional 方法调用普通方法
  • 普通方法调用普通方法

如果我调用 dao.refresh(l),我得到:“ID 为“”的对象由不同的对象管理器管理”,所以 Spring 可能正在使用与 DAO 不同的持久性管理器,是这样吗?这 原因?

这是我的弹簧配置(可能相关):

<bean id="pmf" class="org.datanucleus.api.jdo.JDOPersistenceManagerFactory" destroy-method="close">
  <property name="connectionDriverName" value="com.mysql.jdbc.Driver"/>
  ...
  <constructor-arg>
    <map>
      <entry key="datanucleus.autoCreateSchema" value="true" />
    </map>
  </constructor-arg>
</bean>
<bean id="myPmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
  <property name="targetPersistenceManagerFactory" ref="pmf" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
  <property name="persistenceManagerFactory" ref="myPmfProxy" /> 
</bean>
<bean id="JDODao" class="sw.JDODao">
  <property name="persistenceManagerFactory" ref="myPmfProxy" /> 
</bean>

I am using Datanucleus, JDO and Spring's declarative @Transactional management woven with Aspect-J.

But when a 'normal' method gets a persistent object from a @Transactional method, the object's state will become transient (the persistence manager seems to be removed) and the object is no longer persistent.

Example:

public class Example {

    public void test() throws Exception {
       Login l = getLogin();                          
       JDOHelper.getObjectState(l);              // transient instead of persistent
       l.getSomeOtherPersistentObj().doStuff();  // NullpointerException :(
    }

    @Transactional
    private Login getLogin() {
        // do transactional stuff here
        // ..
        return dao.find(Login.class, 1);
    }
}

Why is this and how can I fix it without adding @Transactional in places where transactions are not needed? The following does (obviously) work so this indicates that a transactional as well as a non-transactional connection can be made:

  • A @Transactional method calls a @Transactional method
  • A @Transactional method calls a normal method
  • A normal method calls a normal method

If I call dao.refresh(l), I get: 'Object with id "" is managed by a different Object Manager', so maybe Spring is working on a different persistence manager than the DAO, is this the cause?

Here's my spring configuration (it might be relevant):

<bean id="pmf" class="org.datanucleus.api.jdo.JDOPersistenceManagerFactory" destroy-method="close">
  <property name="connectionDriverName" value="com.mysql.jdbc.Driver"/>
  ...
  <constructor-arg>
    <map>
      <entry key="datanucleus.autoCreateSchema" value="true" />
    </map>
  </constructor-arg>
</bean>
<bean id="myPmfProxy" class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
  <property name="targetPersistenceManagerFactory" ref="pmf" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jdo.JdoTransactionManager">
  <property name="persistenceManagerFactory" ref="myPmfProxy" /> 
</bean>
<bean id="JDODao" class="sw.JDODao">
  <property name="persistenceManagerFactory" ref="myPmfProxy" /> 
</bean>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我恋#小黄人 2024-12-10 19:11:33

事实证明,我的对象需要可拆卸才能做到这一点。

我将 (detachable="true") 添加到我的 @PersistenceCapable 注释中,并设置以下 datanucleus 选项:

<entry key="datanucleus.DetachAllOnCommit" value="true" />
<entry key="datanucleus.detachedState" value="all" />

It turned out that my objects need to be detachable to do this.

Iv'e added (detachable="true") to my @PersistenceCapable annotations and set the following datanucleus options:

<entry key="datanucleus.DetachAllOnCommit" value="true" />
<entry key="datanucleus.detachedState" value="all" />
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文