Ebean multiple @ManyToMany delivers strange behavior

无人久伴 提交于 2019-12-11 08:46:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!