使用Seam POJO进行手动事务处理

6

如果在将Seam部署为WAR时不使用EJBs,使用数据库事务的最佳实践是什么?

默认情况下,Seam JavaBean支持事务。我可以使用@Transactional注释一个方法,这将确保需要一个事务。或者我可以使用@Transactional(NEVER)或@Transactional(MANDATORY)。但我找不到如何创建自己的事务,设置超时时间,开始并提交/回滚的方法。

我尝试使用:

UserTransaction utx = Transaction.instance();
utx.setTransactionTimeout(2000);
utx.begin();

但是如果事务已经在进行中,则忽略它,或者如果我使用@Transactional(NEVER)注解该方法,则返回javax.transaction.NotSupportedException。

非常感谢任何帮助。谢谢。


请提供 @Transactional 的完全限定名称。 - Bozho
org.jboss.seam.annotations.Transactional - Damo
2个回答

8
如您所知,事务管理是一个横切关注点。因此,在那些不是其主要关注点的模块中散布代码并不是一个好主意。
如果您在非EJB环境中使用JTA UserTransaction,则JTA可用(Apache Tomcat不支持JTA)。
第一条规则:
Seam事务管理默认为所有JSF请求启用(Seam 2.0+)。
我认为“Seam事务管理”听起来比“由Seam管理的事务”更好。它意味着Seam在幕后负责调用begin和commit。Seam通过使用Seam事务管理器扮演事务管理器的角色。
第一种情况:POJO + JTA可用(Apache Tomcat不支持JTA)
Seam使用的事务管理器:org.jboss.seam.transaction.UTtransaction
在JTA可用的非EJB环境(war)中默认启用(JBoss支持JTA)
如果您正在使用JPA EntityManager或Hibernate Session,则需要注册它们以允许Seam管理事务边界。
请参阅9.3. Seam管理的持久性上下文,了解如何设置Seam管理的持久性上下文(通过使用@In注入)。然后,通过使用@In(作用域为ScopeType.CONVERSATION)来注入EntityManager(EntityManager)或Session(Hibernate)。
@Name("businessService")
public class BusinessServiceImpl implementes BusinessService {

    @In
    private EntityManager entityManager;

    public void doSomething() {
        // You do not need to call entityManager().getTransaction().begin();
        // because Seam Transaction Manager takes care of it
        // By using proxies
        // Therefore, if you call entityManager().getTransaction().begin()
        // You will get IllegalStateException

        // Some EntityManager operations persist, find etc

        // You do not need to call entityManager().getTransaction().commit();
        // because Seam Transaction Manager takes care of it
        // By using proxies
    }

}

在幕后,Seam事务管理器通过调用joinTransaction方法将EntityManager(JPA)或Session(Hibernate)注册到活动的JTA UserTransaction中。

第二种情况:POJO + RESOURCE_LOCAL(Hibernate或JPA)事务

Seam使用的事务管理器(JPA):org.jboss.seam.transaction.EntityTransaction

Seam使用的事务管理器(Hibernate):org.jboss.seam.transaction.HibernateTransaction

请参见9.3.Seam托管的持久性上下文如何设置Seam托管的持久性上下文(通过使用@In注入)

在幕后,Seam事务管理器通过使用代理来处理调用底层技术中的begin和commit操作

第三种情况:EJB

Seam使用的事务管理器:org.jboss.seam.transaction.CMTTransaction

在EJB环境中默认启用。请注意,在这种情况下,Seam不控制容器管理的事务。

敬礼,


6
我目前的工作方式如下:
//don't use @Transactional annotation
public void doStuff() {
  UserTransaction userTx = (UserTransaction) org.jboss.seam.Component.getInstance("org.jboss.seam.transaction.transaction");
  userTx.setTransactionTimeout(10 * 60);  //set timeout to 60 * 10 = 600 secs = 10 mins
  userTx.begin();

  /*If entity manager is created before the transaction is started (ie. via Injection) then it must join the transaction */
  entityManager.joinTransaction();

  //do stuff    

  entityManager.persist(user);
  entityManager.flush();   //logs will show an insert at this point

  userTx.commit();   //or rollback()
}

但如果已经有一笔交易正在进行,并且您想要加入该交易,那么您需要使用userTx.isActive()等方法。


太棒了!我可以使用这个来避免“事务未激活”异常。 - prageeth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接