【发布时间】:2016-01-22 16:44:06
【问题描述】:
我有一个实体MXGroup,它可以通过status 属性在逻辑上删除。
该实体通过 Hibernate 持久化到 MySQL 数据库中。
当我通过我的 JSF 页面创建此实体时,将其持久化,然后尝试更新此实体的 status 列而不在创建和逻辑删除之间重新加载我的页面,对状态列的更改不会持久化。
实体显然在 Hibernate 的缓存和数据库中。更新属性然后调用merge 不会将更改合并到数据库中。
合并实体后,我在实体管理器上明确调用了flush 和getTransaction().commit(),但仍然没有骰子。
如果我刷新我的页面(可能会得到一个不同的EntityManager,因为我的EntityManagers 是对话范围的)然后我可以突然删除我的MXGroup 而不会出现任何问题。
我知道我可以采取一些解决方法 - 所以这主要是关于为什么会发生这种情况的学术练习......
我的MXGroup 实体通过 ajax 的 RESTful 接口加载,方法如下:(PersonalGroup 实体扩展 MXGroup 实体)
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("personal/")
public Response restPersonalGroups() {
return Response.ok().entity(serializePersonalGroups()).build();
}
public String serializePersonalGroups() {
final List<PersonalGroup> personalGroupsList = this.userGroupService.getPersonalGroups();
String personalGroups = serializeGroupList(personalGroupsList);
return personalGroups;
}
userGroupService.getPersonalGroups() 方法看起来像:
public List<PersonalGroup> getPersonalGroups() {
CriteriaBuilder builder = this.getEntityManager().getCriteriaBuilder();
CriteriaQuery<PersonalGroup> criteria = builder.createQuery(PersonalGroup.class);
Root<PersonalGroup> root = criteria.from(PersonalGroup.class);
List<Predicate> predicateList = new ArrayList<Predicate>();
predicateList.addAll(Arrays.asList(getCommonPredicates(PersonalGroup.class, builder, criteria, root)));
predicateList.add(builder.equal(root.get(PersonalGroup_.user), getUser()));
TypedQuery<PersonalGroup> query = this.getEntityManager().createQuery(
criteria.select(root)
.where(predicateList.toArray(new Predicate[predicateList.size()]))
.orderBy(builder.asc(root.get(MXGroup_.name)))
.distinct(true));
List<PersonalGroup> personalGroups = query.getResultList();
for (PersonalGroup pg : personalGroups) {
this.getEntityManager().refresh(pg);
}
return personalGroups;
}
getCommonPredicates 在这种情况下只添加一个谓词检查 status == 1 是否存在
删除功能如下:
public void deletePersonalGroup() throws BadLoginNameException, UniqueUserLoginException {
String groupIdStr = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("groupId");
int groupId = Integer.parseInt(groupIdStr);
MXGroup group = this.userGroupService.findMXGroup(groupId);
group.setStatus(0);
this.userGroupService.mergeMXGroup(group);
this.userGroupService.forceCommit();
}
mergeMXGroup 是:
@Override
public void mergeMXGroup(MXGroup group) {
super.merge(group);
}
其super 实现如下:
protected <T> T merge(T entity) {
if (canUseService() && beforeMergeEntity(entity)) {
T merge = this.getEntityManager().merge(entity);
return merge;
}
return null;
}
最后我像这样强制刷新和提交:
public void forceCommit() {
this.getEntityManager().getTransaction().commit();
this.getEntityManager().flush();
}
几乎可以肯定,RESTful 接口与删除代码有不同的实体管理器,因为删除代码是 CDI 管理的,而 RESTful 接口是 EJB。但我会认为刷新和提交会解决问题?事实上,这是我第一次在整个项目中明确地刷新/提交......
有什么想法吗?
【问题讨论】:
-
您的
@OverridemergeMXGroup方法不返回托管实体。当它被 EL 连接到视图时,尝试返回托管实例并在 JSF/CDI bean 中交换它。 -
谢谢@Geinmachi 没有发现,但不相信它会阻止数据持久保存在数据库中,不是吗?
标签: hibernate jpa merge commit