2014-02-09 185 views
0

这里是我所得到的:为什么在参数中没有保存输出参数?

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()尽管用户坚持在DB(MySQL的,我用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; 
    } 
} 
+0

UserService从'@ManagedBean @ViewScoped public class UserController {@EJB private UserService service; }'。我终于猜测题目问题的答案是persist()需要是异步的。 –

回答

0

如果检查the documentation for EntityManager你可以看到。

空隙冲洗()

同步持久上下文到底层数据库。

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

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

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

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

编辑

每个EJB由Java EE容器管理。您刚刚注意到这种管理的效果。每个方法调用都处于事务中,也可能与此同步有关。

要知道为什么它的发生,你可以拨打:

Thread.currentThread().getStackTrace() 

在你UserService.register,并打印堆栈跟踪元素的全阵列。您将得到类似于:

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的合同。例如,他们关心交易,也可能在您的情况下关于使用数据库同步实体。

+0

如果我只是'em.persist(u);返回u;'u'我得到的是正确的id - 所以在方法返回时调用flush或refresh。我用我的类的注释编辑了问题 - 我在'UserService .register()'上运行事务吗? (虽然我的问题是_why_坚持不刷新我会满意_how_ :) –

+0

我已更新帖子回答你的问题 – zimi

+0

谢谢 - 我已经看到堆栈跟踪和\ _ \ _生成\ _而不必调用' Thread.currentThread()。getStackTrace()'(笑话),但你的回答是有道理的:)。为了完美,我希望有一些链接指向这个同步的文档。 @stateless是否对交易产生影响? –

相关问题