我正在使用带有EJB / JPA的JBoss EAP 6.1.0。我有一个User对象,他有几个他所属的组,我正在尝试使用三步法在数据库中创建它:
我的问题是步骤(3)总是返回null,因为尚未发生提交。在步骤2和3之间添加em.flush()
没有帮助。我正在避免使用任何组的@CASCADE注释,因此只保存用户并且不能选择组级联。以下是示例代码:
@Stateless
public class RegistrationService {
@EJB
UserDao userDao;
public User registerNewUser(User user, List<Group> groups) {
userDao.saveNewUser(user);
userDao.saveNewGroupsToUser(user, groups);
return userDao.findUser(user);
}
}
这是一个简化的UserDao:
@Stateless
public class UserDao {
@PersistenceContext
private EntityManager em;
public void saveNewUser(User user) {
em.persist(user);
}
public void saveNewGroupsToUser(User user, List<Group> groups) {
for (Group group : groups) {
GroupToUser groupToUser = new GroupToUser(user, group);
em.persist(groupToUser);
}
public User findUser(User user) {
return em.createQuery("from User where user = :userId")
.setParameter("userId",user.getUserId())
.getSingleResult();
}
}
我发现如果我使用findUser(User)
注释@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
方法,它会按预期工作。这是为什么呢?我以为registerNewUser()
创建了一个大事务,然后findUser()会创建一个嵌套事务,它不应该知道保存了吗?
答案 0 :(得分:2)
我认为你应该在第1步之后(保存用户之后)添加em.flush(),因为它将执行SQL以保存新用户。
第二件事,从代码看似乎使用了容器管理事务。 CMT不允许嵌套交易。因此,基本上添加REUIRED_NEW属性可能会强制刷新以前的保存SQL查询。确认这一点的一种方法是记录SQL查询
答案 1 :(得分:0)
我最终只是在@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
方法上使用了findUser()
。由于容器管理事务(CMT)不允许嵌套事务,因此这似乎刷新了以前的SQL更新/插入语句,允许select按预期工作。