gpt4 book ai didi

java - 合并时的 JPA OrderColumn 空值

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:56:01 27 4
gpt4 key购买 nike

我在 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com