问题
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:
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);
}
}
and
@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);
Ebean.commitTransaction();
}
as the values in Foo.bars2
aren't persisted (e.g. foo.getBars2().size() == 0
).
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')
without the needed insert into foo_bar2 (foo_id, bar_id) values (1, 2)
query.
Does someone know what's going on here?
回答1:
This is interesting case. I made some tests and there are results:
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);
produced 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 (bar_id, foo_id) values (2, 1)
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);
gave result:
first bar:bar1
second bar:bar1
and produced queries:
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 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.
While I changed code to:
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);
then Ebean referred two times to foo_bar2
table.
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.
来源:https://stackoverflow.com/questions/24099008/ebean-multiple-manytomany-delivers-strange-behavior