Spring JPA双向@ManyToOne不';行不通
我们用双向@manytone关系链接了两个实体,如下所示:Spring JPA双向@ManyToOne不';行不通,spring,spring-boot,jpa,spring-data-jpa,Spring,Spring Boot,Jpa,Spring Data Jpa,我们用双向@manytone关系链接了两个实体,如下所示: @Entity @Setter @Getter @Builder @NoArgsConstructor @AllArgsConstructor(access = AccessLevel.PRIVATE) public class Foo { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToMa
@Entity
@Setter
@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Foo {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(fetch = FetchType.LAZY, mappedBy = "foo")
private Set<Bar> bars;
}
@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class Bar {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "foo_id")
private Foo foo;
}
@实体
@塞特
@吸气剂
@建筑商
@诺尔格构装师
@AllArgsConstructor(access=AccessLevel.PRIVATE)
公开课Foo{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@OneToMany(fetch=FetchType.LAZY,mappedBy=“foo”)
私人酒吧;
}
@实体
@吸气剂
@塞特
@建筑商
@诺尔格构装师
@AllArgsConstructor(access=AccessLevel.PRIVATE)
公共类酒吧{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
私人长id;
@许多酮
@JoinColumn(name=“foo\u id”)
私人富福;
}
当我创建Foo实体和Bar实体,并尝试将创建的Foo设置为Bar时,更改不会反映在另一侧
以下是我的集成测试的代码:
Foo foo = fooRepository.save(Foo.builder()...build());
Bar bar = new Bar();
bar.setFoo(foo);
bar.set...();
barRepository.save(bar);
Foo updatedFoo = fooRepository.findById(foo.getId()).get();
List<Bar> bars = updatedFoo.getBars(); // this is null
Foo-Foo=fooRepository.save(Foo.builder()…build());
条形=新条形();
巴.塞富(富);
酒吧设置…();
barRepository.save(bar);
Foo updatedFoo=fooRepository.findById(Foo.getId()).get();
列表栏=updatedFoo.getBars();//这是空的
我不知道为什么fetched foo中的条为空。当我尝试从存储库中获取给定的条时,我可以在这一侧看到保存的Foo。简短回答
- JPA要求您设置关系的双方
- 只要您设置了拥有方
,数据库就会随着关系的更改而更新因此您的数据库是正确的bar.setFoo()
- 非拥有方
仅在手动设置时反映数据库中的内容,或强制刷新或重新加载,例如foo
entityManager.refresh(foo)
- 在事务会话中,对存储库的每个调用都不会转换为数据库调用。由于hibernate all ready在第1行中将
作为foo
实体, 调用时,managed
fooRepository.findById(foo.getId()).get()代码>JPA不发出select语句如果您搜索
和事务性写在后面
,您可以找到更多信息可重复读取
-Foo-Foo=fooRepository.save(Foo.builder()…build())
成为托管实体,由于foo
保证,JPA将为可重复读取
的所有后续检索返回相同的foo
foo
- 如果在保存后调用
,它甚至不会进入数据库fooRepository.findById(fooId)
barRepository.save(bar)代码>-
也会被管理条形图
和foo
都是托管实体,但是foo说我没有任何bar
s,bar说我知道一个bar
,因为你没有设置foo
。这在内存中是不正确的,因为您必须显式地设置关系的两侧foo.getbar().add(bar)
- 如果您完成当前的
,而不将条形图添加到foo中,然后在另一个transactional中调用transactional方法
,它将向您显示它获取foo和条形图fooRepository.findById(fooId)
@OneToMany(fetch = FetchType.LAZY, mappedBy = "foo",cascade= CascadeType.ALL)
private Set<Bar> bars;
@ManyToOne(cascade= CascadeType.ALL)
@JoinColumn(name = "foo_id")
private Foo foo;
barRepository.save(bar)将不会持久保存foo
添加cascade时,它将保留这两个实体,或者您需要使用fooRepository手动保存foo实体。是的,使用@Transactional,您可以尝试初始化集合即私有集合栏;=新HashSet();并删除fetch。
Foo foo = fooRepository.save(Foo.builder()...build());
Bar bar = new Bar();
bar.setFoo(foo);
bar.set...();
barRepository.save(bar);