我有三个类(A,B,C),它们具有OneToMany关系
A <>-- B <>-- C
代码:
@Getter @Setter
@Entity
public class A {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "a")
private List<B> bList;
private String name;
}
@Getter @Setter
@Entity
public class B {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(fetch = FetchType.EAGER)
private A a;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "b")
private List<C> cList;
private String name;
}
@Getter @Setter
@Entity
public class C {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne(fetch = FetchType.EAGER)
private B b;
}
我应该如何正确填充数据?当我尝试这样的事情时:
A a = new A();
a.setName("A-1");
aRepository.save(a);
B b1 = new B();
b1.setName("B-1");
b1.setA(a);
bRepository.save(b1);
B b2 = new B();
b2.setName("B-2");
b2.setA(a);
bRepository.save(b2);
for (int i = 1; i <= 9; i++ ) {
C c = new C();
c.setName("C-"+i);
c.setB(b1);
cRepository.save(c);
}
我在数据库中获得了正确填充的数据:
+----+------+
| ID | NAME |
+----+------+
| 1 | A-1 |
+----+------+
+----+------+------+
| ID | NAME | A_ID |
+----+------+------+
| 1 | B-1 | 1 |
+----+------+------+
| 2 | B-2 | 1 |
+----+------+------+
+----+------+------+
| ID | NAME | B_ID |
+----+------+------+
| 1 | C-1 | 1 |
+----+------+------+
| 2 | C-2 | 1 |
+----+------+------+
| 3 | C-3 | 1 |
+----+------+------+
| 4 | C-4 | 1 |
+----+------+------+
| 5 | C-5 | 1 |
+----+------+------+
| 6 | C-6 | 1 |
+----+------+------+
| 7 | C-7 | 1 |
+----+------+------+
| 8 | C-8 | 1 |
+----+------+------+
| 9 | C-9 | 1 |
+----+------+------+
但是当我试图从存储库中获取数据时出现了问题:
这些测试没问题:
assertThat(cRepository.findOne(1l)).isNotNull();
assertThat(cRepository.findOne(1l).getB()).isNotNull();
assertThat(cRepository.findAll()).hasSize(9);
assertThat(bRepository.findAll()).hasSize(2);
assertThat(bRepository.findOne(1l).getCList().size()).isEqualTo(9);
但是这个失败了:
assertThat(aRepository.findOne(1l).getBList().size()).isEqualTo(2);
它返回10条记录。查询SELECT * FROM B WHERE A_ID = 1
会返回2条记录,那么请您详细说明我做错了什么?
答案 0 :(得分:2)
它的奇怪的休眠行为是由EAGER类型使用OUTER JOINS这一事实引起的。你得到与B相关的每个C对象的重复B对象。我有类似的问题,我找到的唯一解决方案是将fetchType更改为LAZY或将List更改为Set。
您有更好的解释:Hibernate Criteria returns children multiple times with FetchType.EAGER或Duplicates in OneToMany annotated List
答案 1 :(得分:0)
您需要将其更改为以下内容:
B b1 = new B();
b1.setName("B-1");
b1.setA(a);
a.getBList().add(b1);
bRepository.save(b1);
B b2 = new B();
b2.setName("B-2");
b2.setA(a);
a.getBList().add(b2);
bRepository.save(b2);
aRepository.save(a);
现在我身边的一些信息。理论上它也可以在没有三个额外行的情况下工作,但前提是你使hibernate缓存无效。我想也许如果你分开a和dann得到a,它会返回正确的结果。一般建议,尽可能避免双向映射。如果您需要,请在
中添加以下内容public void addB(B b) {
b.setA(this);
a.getBList().add(b);
}
发布到ManyToOne。没有必要添加急切的提取,因为这是默认值。