有没有办法判断是否在JTA中启动了新的交易

时间:2017-09-20 09:39:04

标签: java hibernate jpa java-ee jta

我使用Wildfly作为我的Java EE服务器。我们有一个框架,我们用它来实现一种命令设计模式。

我会尝试尽可能简单地描述工作流程:

  • 每个命令都是一个存储命令信息的实体(执行时间戳,成功状态等)。
  • 每个Command都有执行businesslogic的CommandEJB
  • 我们所有的命令都是从Command类扩展而来的,它们的EJB是从CommandEJB类扩展的
  • CommanEJB调用为特定命令重写的run方法,其中为该特定命令执行业务逻辑
  • 之后,CommandEJB尝试持久化Command对象(其中包含有关命令执行的信息,如第1点所述)
  • 如果一个CommandEJB实现正在创建一个实体并将其持久化在它的run方法实现中,那么我们总是在特定命令和该实体之间进行双向关联

我会尝试编写一些伪代码来解释它是如何工作的:

我有一个名为Person的实体,我有一个CreatePersonCmd,它是应该创建一个新人并将其持久保存到数据库的命令。之后,框架将CreatePersonCmd持久化到数据库。在命令执行时,Person实体和CreatePersonCmd实体通过

链接

person.setCmd(cmd);

cmd.setPerson(person);

我有一个调用命令的SAOP Web服务:

@Stateless
@WebService
public class MyWebService {
CreatePersonCmd cmd = new CreatePersonCmd();
executor.execute(cmd);
}

我的CreatePersonCmd是CreatePersonCommand和Person之间关系的所有者,所以看起来像这样:

public class CreatePersonCmd {
@JoinColumn
@OneToOne
private Person person;
}

关系的另一面是人:

public class Person{
@OneToOne(mappedBy="person")
private CreatePersonCmd createPersonCmd;
}

在我的CreatePersonEJB(调用其run方法实现)中:

public class CreatePersonCmdEJB extends CommandEJB {

public void run() {

    Person person = new Person("John Doe");
    createPersonCmd.setPerson(person);
    person.setCreatePersonCmd(createPersonCmd);
    em.persist(person);

}

之后,CommandEJB继续执行并尝试保存命令:

em.persist(createPersonCmd);

但是,执行永远不会到达最后一行,我在以下位置得到例外:

em.persist(person);

例外是:

Not-null property references a transient value - transient instance must be saved before current operation

奇怪的是,如果我让Person成为这段关系的拥有者,那么一切都运转良好。

我做了一个简单的例子,没有我们的框架,它有2个实体Customer和Address,它们也有双向的OneToOne关系,但是我做的测试它总是很好,无论我使用的持久性顺序如何。

这是伪代码:

Customer c = new Customer("John Doe");
Address a = new Address("MyStreet", 1123);

c.setAddress(a);
a.setCustomer(c);

em.persist(c);
em.persist(a);

无论持久性的顺序是什么(地址或客户优先,如果我有两条线,它总是很好)

然而,在我们的框架中,似乎tra.actions在em.persist(person)之后结束,我在框架源代码中看不到em.flush()。

我是否有任何方式可以知道我是否在同一笔交易中?我试图通过em.getTransaction()获取交易,但我得到A JTA EntityManager cannot use getTransaction(),可能是因为转换在Java EE中由应用程序容器管理。

1 个答案:

答案 0 :(得分:0)

如果已插入createPersonCmd,则必须将其添加到当前工作集。 这可以通过

来完成
createPersonCmd = em.merge(createPersonCmd)