每当我尝试在模型中对CascadeType.ALL使用多个@ManyToMany属性时,我都会遇到Ebean(版本3.2.2)的奇怪行为.
I experience strange behavior with Ebean (version 3.2.2), whenever I try to use multiple @ManyToMany attributes with CascadeType.ALL in a model.
我做了一个简化的例子来重现该问题:
I've made a simplified example to reproduce the problem:
我有以下两个实体(省略了getters)
I have the following two Entities (getters omitted)
@Entity public class Foo extends Model { @Id @GeneratedValue private Long id; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "foo_bar1") private List<Bar> bars1; @ManyToMany(cascade = CascadeType.ALL) @JoinTable(name = "foo_bar2") private List<Bar> bars2; public void addBar1(Bar bar1) { bars1.add(bar1); } public void addBar2(Bar bar2) { bars2.add(bar2); } }和
@Entity public class Bar extends Model { @Id @GeneratedValue private Long id; private String name; @ManyToMany(mappedBy = "bars1") private List<Foo> foos1; @ManyToMany(mappedBy = "bars2") private List<Foo> foos2; public Bar(String name) { this.name = name; } }但是当我执行以下测试时,它会导致奇怪的行为
but it leads to strange behavior whenever I execute the following test
@Test public void cascadeTest() { Ebean.beginTransaction(); Foo foo = new Foo(); Bar bar1 = new Bar("bar1"); Bar bar2 = new Bar("bar2"); foo.addBar1(bar1); foo.addBar2(bar2); Ebean.save(foo); EbeanmitTransaction(); },因为Foo.bars2中的值不会保留(例如foo.getBars2().size() == 0).
as the values in Foo.bars2 aren't persisted (e.g. foo.getBars2().size() == 0).
Ebean生成以下SQL查询
Ebean generates the following SQL queries
insert into foo (id) values (1) insert into bar (id, name) values (1,'bar1') insert into foo_bar1 (foo_id, bar_id) values (1, 1) insert into bar (id, name) values (2,'bar2')没有所需的insert into foo_bar2 (foo_id, bar_id) values (1, 2)查询.
有人知道这是怎么回事吗?
Does someone know what's going on here?
推荐答案这是一个有趣的情况.我做了一些测试,结果是:
This is interesting case. I made some tests and there are results:
在栏上添加foo后,Ebean正确保存了关系. 所以下面的代码:
After adding foo to bar lists Ebean saved relations correctly. So the following code:
Foo foo = new Foo(); Bar bar1 = new Bar("bar1"); Bar bar2 = new Bar("bar2"); foo.addBar1(bar1); foo.addBar2(bar2); bar1.foos1.add(foo); bar2.foos2.add(foo); Ebean.save(foo);产生以下SQL查询:
insert into foo (id) values (1) insert into bar (id, name) values (1,'bar1') insert into foo_bar1 (foo_id, bar_id) values (1, 1) insert into bar (id, name) values (2,'bar2') insert into foo_bar2 (bar_id, foo_id) values (2, 1)但是当我想阅读foo并且它是条形时,我收到了有趣的结果. 以下代码:
But when I wanted read foo and it's bars I received interesting result. Following code:
Foo ffoo = Ebean.find(Foo.class, 1L); System.out.println("first bar:"+ffoo.bars1.get(0).name); System.out.println("second bar:"+ffoo.bars2.get(0).name);给出结果:
first bar:bar1 second bar:bar1并产生查询:
select t0.id c0 from foo t0 where t0.id = 1 select int_.foo_id c0, t0.id c1, t0.name c2 from bar t0 left outer join foo_bar1 int_ on int_.bar_id = t0.id where (int_.foo_id) in (1) select int_.foo_id c0, t0.id c1, t0.name c2 from bar t0 left outer join foo_bar1 int_ on int_.bar_id = t0.id where (int_.foo_id) in (1)Ebean在查找bar1时应参考foo_bar1表,而在查找bar2时应参考foo_bar2表.但是在两种情况下,Ebean都查询了foo_bar1表.
Ebean should refer to foo_bar1 table while looking for bar1 and to foo_bar2 table while looking for bar2. But in both cases Ebean queried foo_bar1 table.
当我将代码更改为:
Foo ffoo = Ebean.find(Foo.class, 1L); System.out.println("second bar:"+ffoo.bars2.get(0).name); System.out.println("first bar:"+ffoo.bars1.get(0).name);然后Ebean两次引用foo_bar2表.
then Ebean referred two times to foo_bar2 table.
对于Ebean来说,似乎两个@ManyToMany关系太多了.我假设Ebean假设两个表之间只能有一个可连接的节点.并且它的名称在第一次查询后被缓存.
It seems that two @ManyToMany relations is too many for Ebean. I suppose that Ebean assumes that there can be only one jointable between two tables. And it's name is cached after first query.
更多推荐
Ebean多个@ManyToMany提供奇怪的行为
发布评论