【问题标题】:Hibernate entity property not being persisted to the database, despite flush and transaction commit尽管刷新和事务提交,休眠实体属性没有被持久化到数据库中
【发布时间】:2016-01-22 16:44:06
【问题描述】:

我有一个实体MXGroup,它可以通过status 属性在逻辑上删除。 该实体通过 Hibernate 持久化到 MySQL 数据库中。 当我通过我的 JSF 页面创建此实体时,将其持久化,然后尝试更新此实体的 status 列而不在创建和逻辑删除之间重新加载我的页面,对状态列的更改不会持久化。

实体显然在 Hibernate 的缓存和数据库中。更新属性然后调用merge 不会将更改合并到数据库中。

合并实体后,我在实体管理器上明确调用了flushgetTransaction().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。但我会认为刷新和提交会解决问题?事实上,这是我第一次在整个项目中明确地刷新/提交......

有什么想法吗?

【问题讨论】:

  • 您的 @Override mergeMXGroup 方法不返回托管实体。当它被 EL 连接到视图时,尝试返回托管实例并在 JSF/CDI bean 中交换它。
  • 谢谢@Geinmachi 没有发现,但不相信它会阻止数据持久保存在数据库中,不是吗?

标签: hibernate jpa merge commit


【解决方案1】:

我正在审查有关合并操作语义的规范。

这些情况中的任何一种都可能解释您的问题的原因(或者可能不是):

应用于实体 X 的合并操作的语义为 如下:

  • 如果 X 是分离实体,则 X 的状态将复制到具有相同身份的预先存在的托管实体实例 X' 或新的 已创建 X 的托管副本 X'。
  • 如果 X 是一个新的实体实例,则创建一个新的托管实体实例 X',并将 X 的状态复制到新的托管实体实例 X'。
  • 如果 X 是已移除的实体实例,则合并操作会抛出 IllegalArgumentException(否则事务提交将失败)。
  • 如果 X 是托管实体,则合并操作会忽略它,但是,如果这些关系已使用级联元素值 cascade=MERGE 或cascade=ALL 注释。
  • 如果 X 是合并到 X' 的实体,并引用另一个实体 Y,其中未指定 cascade=MERGE 或 cascade=ALL,则从 X' 导航相同关联会产生对托管对象 Y 的引用' 与 Y 具有相同的持久标识

持久性提供程序不得合并标记为 LAZY 且尚未获取的字段:合并时必须忽略此类字段。

【讨论】:

    【解决方案2】:

    我很确定,这不是您问题的解决方案,但我必须补充一点,您的 forceCommit() 工作顺序错误。

    首先您必须使用flush() 写入数据库,然后提交事务。 (也就是说,如果你需要冲洗的话。)

    【讨论】:

      猜你喜欢
      • 2012-01-09
      • 2013-06-12
      • 2020-12-14
      • 2020-02-14
      • 2011-09-24
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 2015-04-22
      相关资源
      最近更新 更多