JPA OneToMany 仅在第一次更新
JPA OneToMany Only Updates First Time
我正在使用 EclipseLink 并且我有两个基本的 类 比如
@Entity
public class Foo {
@Id
@Column(name="FOO_ID)
private int id;
@Column(name="FOO_NAME")
private String name;
@OneToMany(mappedBy = "foo")
private List<Bar> bars;
}
@Entity
public class Bar {
@Id
@Column(name="BAR_ID")
private it id;
@Column(name="BAR_NAME")
private String name;
@ManyToOne
@JoinColumn(name="FOO_ID")
private Foo foo;
}
然后我有一些代码基本上可以
public void processBar(Foo foo) {
Bar bar = new Bar();
bar.setName("Test");
bar.setFoo(foo);
entityMgr.persist(bar);
List<Bar> bars = foo.getBars();
for (Bar b : bars) {
System.out.println("Bar - id : " + b.getId());
System.out.println("Bar - name : " + b.getName());
}
}
当我进入 webapp 并调用代码(foo 设置良好)时,我可以看到一个 child Bar
的预期输出,其中包含我期望的 ID 和名称。
如果我随后进入一个新会话并 运行 相同的代码,那么我不会看到两个 Bar
,我仍然看到第一个(而且只有第一个)但是Bar
记录已在数据库中创建并正确链接。
如果我在创建新的 Bar
之前添加相同的循环来打印出柱状图,那么在创建 bar
之前和之后我总是会看到一个空列表
在 oneToMany
上设置 fetch = FetchType.EAGER)
给我一个空集。
添加 bar 后合并 foo 没有任何区别。
我需要什么才能使它保持一致?
更新
我现在通过在 Foo
中实现一个 addBar
方法来完成这项工作
public void addBar(Bar b) {
bars.add(b);
}
为关系添加级联
@OneToMany(mappedBy="foo", cascade = CascadeType.ALL)
然后我用 foo.addBar(bar)
替换了 bar 的 persist
最后添加了entityMgr.merge(foo)
现在可以正常工作了,但我仍然不明白为什么原始代码不起作用,所以关于该代码如何工作的问题仍然存在(或者是否必须像我所做的那样完成这里)
您正在使用双向 OneToMany 关系,因此,如果您在关系中添加或删除项目,例如通过提供特殊的 setter,您有责任更新 Java 模型。例如,see this blogpost.
我正在使用 EclipseLink 并且我有两个基本的 类 比如
@Entity
public class Foo {
@Id
@Column(name="FOO_ID)
private int id;
@Column(name="FOO_NAME")
private String name;
@OneToMany(mappedBy = "foo")
private List<Bar> bars;
}
@Entity
public class Bar {
@Id
@Column(name="BAR_ID")
private it id;
@Column(name="BAR_NAME")
private String name;
@ManyToOne
@JoinColumn(name="FOO_ID")
private Foo foo;
}
然后我有一些代码基本上可以
public void processBar(Foo foo) {
Bar bar = new Bar();
bar.setName("Test");
bar.setFoo(foo);
entityMgr.persist(bar);
List<Bar> bars = foo.getBars();
for (Bar b : bars) {
System.out.println("Bar - id : " + b.getId());
System.out.println("Bar - name : " + b.getName());
}
}
当我进入 webapp 并调用代码(foo 设置良好)时,我可以看到一个 child Bar
的预期输出,其中包含我期望的 ID 和名称。
如果我随后进入一个新会话并 运行 相同的代码,那么我不会看到两个 Bar
,我仍然看到第一个(而且只有第一个)但是Bar
记录已在数据库中创建并正确链接。
如果我在创建新的 Bar
之前添加相同的循环来打印出柱状图,那么在创建 bar
在 oneToMany
上设置 fetch = FetchType.EAGER)
给我一个空集。
添加 bar 后合并 foo 没有任何区别。
我需要什么才能使它保持一致?
更新
我现在通过在 Foo
addBar
方法来完成这项工作
public void addBar(Bar b) {
bars.add(b);
}
为关系添加级联
@OneToMany(mappedBy="foo", cascade = CascadeType.ALL)
然后我用 foo.addBar(bar)
persist
最后添加了entityMgr.merge(foo)
现在可以正常工作了,但我仍然不明白为什么原始代码不起作用,所以关于该代码如何工作的问题仍然存在(或者是否必须像我所做的那样完成这里)
您正在使用双向 OneToMany 关系,因此,如果您在关系中添加或删除项目,例如通过提供特殊的 setter,您有责任更新 Java 模型。例如,see this blogpost.