为什么参数不是持久输出参数?

时间:2014-02-09 18:46:23

标签: jpa entitymanager flush

这是我得到的:

public User register(User u) {
    em.persist(u);
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 0
    em.flush();
    System.out.println("USER id: " + u.getIduser()); // INFO: USER id: 1
    return u;
}

即使我忽略了对flush()的调用,但用户 仍保留在数据库中(MySQL,我使用eclipse中的glasssfish 4)。那么为什么我需要调用flush来设置id(在方法退出时显然是自动调用,但是我想在register()中使用id)?

顺便说一句,flush()被调用的事实是否表明事务正在进行?

更新:这是EJB类:

@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public User register(User u) {
        em.persist(u);
        // em.flush(); // not needed - called on exit - maybe I have a
        // transaction after all
        return u;
    }
}

1 个答案:

答案 0 :(得分:0)

如果您选中the documentation for EntityManager,则可以看到。

  

void flush()

     

将持久性上下文与基础数据库同步。

Persist()不会刷新您的实体,但它会对数据库执行操作。

要获取您的ID,您必须同步您的实体。

AFAIR flush()与交易无关。由于JTA管理您的交易。 JTA从EntityTransaction调用方法begin,commit,rollback,它由EntityManager.getTransaction()返回。

如果在实体上调用EntityManager.refresh方法,它也应该同步。

修改

每个EJB都由Java EE Con​​tainer管理。你刚才注意到了这种管理的效果。每个方法调用都在事务中,也可能与此同步。

要了解它为什么会发生,你可以致电:

Thread.currentThread().getStackTrace()

在您的UserService.register中,打印完整的stacktrace元素数组。你会得到类似的东西:

UserService.register(UserService.java:xxx)
SomeGenerated.invoke(SomeGenerated.java:xxx)
SomeGenerated.invoke(SomeGenerated.java:xxx)
UserController.register(UserController.java:xxx)

因此,您不会像预期的那样直接从UserController.register调用UserService.register方法。

这个“SomeGenerated”类关注给你EJB的契约。例如,他们关心的是交易,也可能是关于同步实体与数据库的关系。