这是我得到的:
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;
}
}
答案 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 Container管理。你刚才注意到了这种管理的效果。每个方法调用都在事务中,也可能与此同步。
要了解它为什么会发生,你可以致电:
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的契约。例如,他们关心的是交易,也可能是关于同步实体与数据库的关系。