gpt4 book ai didi

java - Ebean 多个 @ManyToMany 提供奇怪的行为

转载 作者:行者123 更新时间:2023-11-30 03:52:23 24 4
gpt4 key购买 nike

每当我尝试在模型中的 CascadeType.ALL 中使用多个 @ManyToMany 属性时,我都会遇到 Ebean(版本 3.2.2)的奇怪行为。

我制作了一个简化的示例来重现该问题:

我有以下两个实体(省略 setter/getter )

@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;
}
}

但每当我执行以下测试时,它都会导致奇怪的行为

  @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();
}

因为 Foo.bars2 中的值未保留(例如 foo.getBars2().size() == 0)。

Ebean 生成以下 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')

没有所需的插入 foo_bar2 (foo_id, bar_id) 值 (1, 2) 查询。

有人知道这是怎么回事吗?

最佳答案

这是一个有趣的案例。我做了一些测试,有结果:

foo 添加到 bar 后,Ebean 正确保存了关系。
所以下面的代码:

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 时,我收到了有趣的结果。
代码如下:

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 表。

当我将代码更改为:

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 表。

对于 Ebean 来说,两个 @ManyToMany 关系似乎太多了。我认为 Ebean 假设两个表之间只能存在一个可连接的对象。它的名称在第一次查询后被缓存。

关于java - Ebean 多个 @ManyToMany 提供奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24099008/

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