Hibernate一对一双向混淆
Hibernate one to one bidirectional confusion
我有示例代码来检查双向关系是如何工作的。
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK")
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@JoinColumn(name = "a_id", referencedColumnName = "aId")
@OneToOne(mappedBy = "b", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
A a;
}
public void insertAB(){
B b = new B();
b.setName("B-Name");
b.setAddress("B-Address");
A a = new A();
a.setName("A-Name");
a.setAddress("A-Address");
a.setB(b);
b.setA(a);
aRepository.save(a);
}
我可以看到这种 table h2 table:-
答:-
B:-
对于 B table,正如我在代码中提到的那样,我期待一个列 a_id
。
所以如果我尝试像这样检索 B,我会在我的控制器中:-
@GetMapping(value = "/getb/{id}")
public B getB(@PathVariable long id){
var b = bRepository.findById(id).get();
return b;
}
{
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
...........
它就像A链和B链,其中有很多。我在学习hibernate和table的关系。显然我误解了一些东西。我的意图是双向的,当我加载 A 时,我可以访问相关的 B。当我加载 B 时,我可以访问相关的 A。我怎样才能实现这个目标?
这个解决方案并不理想,因为:
- 这只会从 json.
中删除过多的数据
- Hibernate 将执行相同的请求,这可能会降低您的应用程序速度。
- 在 java 实体中设置 jackson 注释 (@JsonManagedReference) 不是一个好习惯。
==> 您可能必须更改关系类型
对于双向一对一关系,这种注释对我有用:-
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@JsonManagedReference // this for parent to avoid infinite recursion
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK") // B table foreign key in A table
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@NotNull
@JsonBackReference // this for child to avoid infinite recursion
@JoinColumn(name = "a_id_FK") // A table foreign key in B table
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private A a;
}
这样我就可以在 A 和 B 中都有外键 table。这样我就可以双向访问了。
我有示例代码来检查双向关系是如何工作的。
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK")
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@JoinColumn(name = "a_id", referencedColumnName = "aId")
@OneToOne(mappedBy = "b", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
A a;
}
public void insertAB(){
B b = new B();
b.setName("B-Name");
b.setAddress("B-Address");
A a = new A();
a.setName("A-Name");
a.setAddress("A-Address");
a.setB(b);
b.setA(a);
aRepository.save(a);
}
我可以看到这种 table h2 table:-
答:-
B:-
对于 B table,正如我在代码中提到的那样,我期待一个列 a_id
。
所以如果我尝试像这样检索 B,我会在我的控制器中:-
@GetMapping(value = "/getb/{id}")
public B getB(@PathVariable long id){
var b = bRepository.findById(id).get();
return b;
}
{
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
"b": {
"name": "B-Name",
"address": "B-Address",
"a": {
"name": "A-Name",
"address": "A-Address",
...........
它就像A链和B链,其中有很多。我在学习hibernate和table的关系。显然我误解了一些东西。我的意图是双向的,当我加载 A 时,我可以访问相关的 B。当我加载 B 时,我可以访问相关的 A。我怎样才能实现这个目标?
这个解决方案并不理想,因为:
- 这只会从 json. 中删除过多的数据
- Hibernate 将执行相同的请求,这可能会降低您的应用程序速度。
- 在 java 实体中设置 jackson 注释 (@JsonManagedReference) 不是一个好习惯。
==> 您可能必须更改关系类型
对于双向一对一关系,这种注释对我有用:-
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class A {
@Id
@GeneratedValue
private long aId;
String name;
String address;
@JsonManagedReference // this for parent to avoid infinite recursion
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "b_id_FK") // B table foreign key in A table
B b;
}
@Getter
@Setter
@NoArgsConstructor
@ToString
@Entity
public class B {
@Id
@GeneratedValue
@Column(name = "b_id_PK")
private long bId;
private String name;
private String address;
@NotNull
@JsonBackReference // this for child to avoid infinite recursion
@JoinColumn(name = "a_id_FK") // A table foreign key in B table
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private A a;
}
这样我就可以在 A 和 B 中都有外键 table。这样我就可以双向访问了。