2012-01-17 251 views
2

我正在使用JSF 2.1,EJB 3.1,JPA 2.0,Glassfish 3.1.1和NetBeans 7.0.1。EJB JPA事务

对于每个实体类,我创建了一个单独的Facade类,例如,使用NetBeans工具的UserFacade和AddressFacade。这两个实体彼此不相关,并且彼此完全独立。但是,我需要在一次事务中将它们放入数据库中,并且如果插入失败,则应该还原另一个应该回滚的数据。我怎样才能做到这一点?据我所知,EJB容器本身管理事务,并且不允许手动控制事务边界。

+1

我发现回答我的问题。如果有人感兴趣,那么这里是[here](http://docs.oracle.com/javaee/6/tutorial/doc/bncij.html)。 – Nurjan 2012-01-20 04:55:15

+1

你的链接和我的答案有区别吗? =) – Marthin 2013-02-25 14:32:08

回答

3

的交易将只要你们俩在同你的实体“触摸”坚持,更新或删除,但是,你说他们是不相关的回滚一切对方无论如何,所以我猜你必须执行2持续存在,这不会在同一个交易范围。

选项1

你可以做一些简单而丑陋的人,这一点,有@PrePersist和@PreUpdate在JPA,你可以确保一切都与以前的坚持。这会造成糟糕的代码库并强制不需要的依赖关系。

选项2

你可以简单地拥有用户和地址之间的关系,这是很自然的。

选项3

第三个选择是使用Bean Managed Transaction

+0

,是否暗示两个实体之间存在关系,并且级联功能是否打开? – b3bop 2012-02-23 18:54:09

+0

是的,这是我的想法。它可能需要一些返工,但有一个用户的地址是很自然的。 – Marthin 2012-02-24 08:09:15

+0

是的,我同意。即使不打算使用级联功能。很难想到地址和用户不应该有明确关系的用例。 – b3bop 2012-02-24 16:10:07

2

在非常基本的情况下,EJB的每个公共方法都在一个事务中执行,该事务在方法内抛出异常时回退。

因此,如果您在同一个方法中创建两个实体,创建将被包装在一个事务中。

+0

在我的情况下,我有两个调用EJB公共方法。例如,userFacade.create(user)和addressFacade(address)在一个方法内部。但是,userFacade和addressFacade是两个不同Facade类的两个不同实例,并且这两个实体被放入两个不同的事务中,我检查了自己。当一个实体未能放入数据库时​​,第二个实体已成功插入数据库。 – Nurjan 2012-01-17 12:09:15

+1

您应该重构您的代码,以便共同执行的操作以相同的业务方法执行。 – tobiasbayer 2012-01-17 12:20:16

2

您可以自行控制交易。该功能被称为Bean-Managed Transactions(BMT)。你可以阅读更多关于他们here

你也需要了解TransactionManagement的事情。 Oracle在这个article中描述了它。

例子:

@Stateless 
@TransactionManagement(TransactionManagementType.BEAN) 
public class MyEJB implements MyEJBLocal { 

    @Resource 
    private EJBContext context; 

    @PersistenceContext 
    private EntityManager em; 

    public void doMyAction() { 
    UserTransaction transaction = context.getUserTransaction(); 
    transaction.begin(); 

    ... create myEntity ... 

    em.persist(myEntity); 
    transaction.commit(); 
    } 

} 
+0

本教程适用于J2EE,对于他正在使用EJB 3而言相当过时。1 – tobiasbayer 2012-01-17 12:08:47

+1

BMT是一个非常古老的概念,所以没有理由downvote;)该链接与J2EE相关,但它包含一些代码示例,而一个新的教程没有。带选项2的 – yatskevich 2012-01-17 12:14:03