4

Spring 和 Guice-persist 都允许@Transactional对访问数据库的方法进行注释,以在未打开时自动创建事务,在方法返回时提交它,在异常时回滚等。

有没有办法在 OSGi 应用程序中不使用 Spring 或 Guice 来获得相同的东西(或类似的可用)?

4

4 回答 4

4

即使在 Guice/Spring @Transactional 容器中运行时,我也经常使用以下代码片段:

public void transact(Runnable runnable) {
    EntityTransaction tx = em.getTransaction();
    boolean success = false;
    tx.begin();
    try {
        runnable.run();
        success = true;
    } finally {
        if (success) {
            tx.commit();
        } else {
            tx.rollback();
        }
    }
}

public <T> T transact(Callable<T> callable) throws Exception {
    EntityTransaction tx = em.getTransaction();
    boolean success = false;
    tx.begin();
    try {
        T result = callable.call();
        success = true;
        return result;
    } finally {
        if (success) {
            tx.commit();
        } else {
            tx.rollback();
        }
    }
}

用法:

dao.transact(new Runnable() {
    public void run() {
        // do stuff in JPA
    }
});

Long count = dao.transact(new Callable<Long>() {
    public Long call() {
        return em.createQuery("select count(*) from Foo", Long.class)
            .getSingleResult();
    }
});

它非常轻巧,可以完成工作。

于 2012-04-13T19:22:54.400 回答
2

Apache Aries 允许您在 blueprint.xml 中以声明方式配置事务。例如:

<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0"
xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0">

<bean
    id="transactedBean"
    class="some.package.BeanImpl">
    <tx:transaction
        method="*"
        value="Required" />

Aries 捆绑包可以放在您选择的 OSGi 框架中。

于 2012-04-13T16:14:26.197 回答
0

一种可能的解决方案是使用 Spring Data JPA,因为它可以在 Spring 容器之外JpaRepositoryFactory您的RepositoryFactorySupport. 获得这项工作的有用信息是如何在 Spring 容器之外使用 Spring Data JPA?.

于 2012-04-13T14:46:42.243 回答
0

如何以不同的方式看待问题,而不是考虑如何准确地实现事务管道,而是考虑包装在事务中的东西,其中 a只是一个包装器,在提交之前transaction并没有多大意义。

这个词可能听起来很奇怪并吓跑了许多开发人员,但它确实很有意义.. 在这里谈论 Monad,或者更好的是......

事务单子

trait Transactional[A] {
  def map[B]( f: A => B): Transactional[B]
  def flatMap[B]( f: A => Transactional[B] ): Transactional[B]
}

这是一篇讨论该方法的帖子,但要点是在没有任何副作用的情况下自由应用函数(例如,在事务中,例如它总是将所有函数输出包装在 中Transactional,直到您准备好提交,然后您调用“承诺”(又名unsafePerformIO)实际上是“改变宇宙”。

以上是在 Scala 中,也许 Monad 一开始可能不是非常明显或可取的东西,但这只是看待问题的另一种方式 => 例如没有框架、AOP、突变等。只是纯函数组合( FTW!)

于 2012-04-13T15:16:22.840 回答