Jakarta ee JPA和EJB托管与非托管
我有点困惑:我有一个带有JSF、EJB和JPA的JavaEE应用程序 我有一个Jakarta ee JPA和EJB托管与非托管,jakarta-ee,jpa,ejb,entity,managed,Jakarta Ee,Jpa,Ejb,Entity,Managed,我有点困惑:我有一个带有JSF、EJB和JPA的JavaEE应用程序 我有一个UserService,它是一个EJB @Stateless public class UserService { public User create(User u) throws ProcessingException { if (!exists(u)) { u = userDao.create(u); addRole(u, RoleType.
UserService
,它是一个EJB
@Stateless
public class UserService {
public User create(User u) throws ProcessingException {
if (!exists(u)) {
u = userDao.create(u);
addRole(u, RoleType.USER);
return u;
} else {
throw new ProcessingException("User " + u.getUsername() + " already exists");
}
}
public boolean hasRole(User u, RoleType r) {
if (u == null || r == null) {
return false;
}
if (!userDao.isManaged(u)) {
u = userDao.find(u.getId());
}
Set<Role> roles = u.getRoles();
...
}
}
当调用addRole(u,RoleType.APPROVER)
时,则u
的状态为非托管。但为什么
我是否总是必须在方法中添加检查,以确保该实体得到管理?一个实体只在从DB获得的同一事务中被管理 在无状态的EJB中,来自客户端的单个方法调用默认情况下计为单个完整事务。所有嵌套EJB方法调用都发生在同一事务中。但是一旦来自客户机的EJB方法调用返回到客户机(例如,JSF/CDI托管bean),事务就结束了。当该方法返回实体时,它将变为非托管 当您将同一个非托管实体传递回服务层时,它仍然处于非托管状态,直到您在其上调用
em.merge()
,或者在@Id
上通过em.find()
从DB获取一个新实体
在您的特定情况下,您可以更改create()
服务方法,如下所示:
public User create(User user, RoleType... roles) {
// ...
for (RoleType role : roles) {
addRole(user, role);
}
return user;
}
因此,您只需在单个事务中执行该作业
userService.create(u, RoleType.APPROVER);
而不是在两次交易中
userService.create(u);
userService.addRole(u, RoleType.APPROVER);
EJB方法的设计应确保客户端(JSF/CDI托管bean)不需要从单个操作方法连续调用多个不同的方法。相反,重构和/或将多个不同服务方法的特定序列合并到单个服务方法中。这保证了作业将在单个事务中进行
另见:
em.merge()
,或者在@Id
上通过em.find()
从DB获取一个新实体
在您的特定情况下,您可以更改create()
服务方法,如下所示:
public User create(User user, RoleType... roles) {
// ...
for (RoleType role : roles) {
addRole(user, role);
}
return user;
}
因此,您只需在单个事务中执行该作业
userService.create(u, RoleType.APPROVER);
而不是在两次交易中
userService.create(u);
userService.addRole(u, RoleType.APPROVER);
EJB方法的设计应确保客户端(JSF/CDI托管bean)不需要从单个操作方法连续调用多个不同的方法。相反,重构和/或将多个不同服务方法的特定序列合并到单个服务方法中。这保证了作业将在单个事务中进行
另见:
em.merge()
,所以不需要对其进行管理,所以当服务方法返回时,所有更改都将被持久化。但是,方法hasRole(用户,角色类型)或updateRole(用户,角色类型)又如何呢。在这里,我总是需要调用find()或merge(),对吗?在hasRole中,只有当关系是延迟加载的,并且父实体是在不同的事务中获得的时,才有必要调用find()或merge()。在updateRole中,由于您最终已经执行了em.merge()
,所以不需要对其进行管理,所以当服务方法返回时,所有更改都将被持久化。