java - 合并时的 JPA OrderColumn 空值

标签 java hibernate jpa jpa-2.0

我在 Hibernate 4.2.5 中使用 JPA 2.0。 我有到相同实体类型的双向映射。

@OneToMany(mappedBy = "parent", cascade = { CascadeType.PERSIST, CascadeType.DETACH }, orphanRemoval = true, fetch = FetchType.EAGER)
@Fetch(FetchMode.JOIN)
@OrderColumn(name = "position", nullable=false)
private List<MenuItem> children = new ArrayList<MenuItem>();

@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinTable(name = "MenuItem_MenuItem", joinColumns = { @JoinColumn(name = "child_id") }, inverseJoinColumns = { @JoinColumn(name = "parent_id") })
private MenuItem parent;

此映射创建了一个包含 parent_id、child_id 和 position 列的可连接对象。当我想将 child 添加到 parent 时,我执行以下操作:

MenuItem newItem = service.persist(..); 
parent.getChildren().add(newItem);
newItem.setParent(parent); 
service.merge(newItem);
service.merge(parent);

生成以下内容:

Hibernate: select nextval ('hibernate_sequence')
Hibernate: insert into MenuItem (menu_id, message, messageId, params, id) values (?, ?, ?, ?, ?)
Hibernate: insert into MenuItem_MenuItem (parent_id, child_id) values (?, ?)

这里的问题是第二个插入不包含 position 属性,因此它保持为空。我做错了什么?

编辑 我正在使用 spring 声明式事务管理,并且我所有的合并和持久化方法都使用 @Transactional 进行注释。会不会有问题?

最佳答案

您的问题是,您将 @OrderColumn 注释放在关联的映射侧。 JPA 和 hibernate 都不支持这一点。 Hibernate 在实体加载时填充 children 列表,但不监视列表中可能发生的更改。向此类列表中添加一个新的 child 不会触发 hibernate 端的任何操作。您必须从另一方(非 mappedBy)管理此类关联:在您的情况下,您必须使用 setParent() 方法。

现在,如果你从 hibernate 的角度来看这种情况,你会意识到,在持久化一个新的子实体(向 MenuItem_MenuItem 表添加新记录)过程中, hibernate 没有机会获得右索引列。实际上,要获得新实体的顺序,您需要查看父实体的映射者列表。但这并不总是可能的。考虑以下代码段:

MenuItem newItem = new MenuItem();
newItem.setParent(parent);
entityManager.persist(newItem);

这里的position栏应该保存什么?

归档目标的正确方法是在 MenuItem 上添加 position 列,如下所示:

private Integer position;

然后用@OrderBy("position")替换@OrderColumn注解:

@OneToMany(mappedBy = "parent", ...)
...
@OrderBy("position")
private List<MenuItem> children = new ArrayList<MenuItem>();

然后添加一个位置重排序方法,像这样:

public void reorder() {
    for (int i = 0; i < getChildren().size(); i++) {
        MenuItem menuItem = getChildren().get(i);
        menuItem.setMyOrder(i);
    }
}

那么你可以尝试使用@PrePersist@PreUpdate 钩子(Hook)来自动调用这个方法。但这有点棘手。由于您必须在正在创建/更新的子项的父项上调用此方法。如果您添加/更新多个 child ,您将最终多次调用此方法。

关于java - 合并时的 JPA OrderColumn 空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21996396/

相关文章:

spring - 使用 Hibernate L2 ehcache 和 spring bootenabledCache 时已经存在另一个未命名的 CacheManager

java - 如何使用 eclipselink jpa 验证模型

java - 使用 Java Persistence 检索所有主键

java - 无法将新的字符串实例变量添加到现有代码中

java拆分每个字母并将其放入表中

java - hibernate “列---不能为空

java - 批量插入中的 Postgres 错误 : relation "hibernate_sequence" does not exist position 17

java - 如何在 GWTHighchart 图表中设置网格?

java - 在 Java ME 和 Android 中对相同数据产生相同的加密结果?

java - 如何使用 SpringBoot 使用 Spring Data JPA 和 MYSQas DB 创建一个简单的 CRUD 应用程序?