@OneToMany如果不加@JoinColumn,系统会自动在主从表中增加一个中间表。
主表:
@Entity(name = "Post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
}
从表:
@Entity(name = "PostComment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
}
如果使用下面代码添加1条主表记录以及3条从表记录:
Post post = new Post("First post");
post.getComments().add(
new PostComment("My first review")
);
post.getComments().add(
new PostComment("My second review")
);
post.getComments().add(
new PostComment("My third review")
);
entityManager.persist(post);
实际上系统会执行7条SQL语句
insert into post (title, id)
values ('First post', 1)
insert into post_comment (review, id)
values ('My first review', 2)
insert into post_comment (review, id)
values ('My second review', 3)
insert into post_comment (review, id)
values ('My third review', 4)
insert into post_post_comment (Post_id, comments_id)
values (1, 2)
insert into post_post_comment (Post_id, comments_id)
values (1, 3)
insert into post_post_comment (Post_id, comments_id)
values (1, 4)
这样如果记录比较多,将会影响到系统性能。我们可以使用@JoinColumn来避免产生中间表:
@JoinColumn(name = "post_id")
但即使是没有中间表,系统任然会执行7条SQL语句:
insert into post (title, id)
values ('First post', 1)
insert into post_comment (review, id)
values ('My first review', 2)
insert into post_comment (review, id)
values ('My second review', 3)
insert into post_comment (review, id)
values ('My third review', 4)
update post_comment set post_id = 1 where id = 2
update post_comment set post_id = 1 where id = 3
update post_comment set post_id = 1 where id = 4
如果我们想删除一条从表记录
post.getComments().remove(0);
系统任然会执行2条语句:
update post_comment set post_id = null where post_id = 1 and id = 2
delete from post_comment where id=2
要想避免这种情况,就要使用@ManyToOne
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();
public void addComment(PostComment comment) {
comments.add(comment);
comment.setPost(this);
}
public void removeComment(PostComment comment) {
comments.remove(comment);
comment.setPost(null);
}
}
@Entity(name = "PostComment")
@Table(name = "post_comment")
public class PostComment {
@Id
@GeneratedValue
private Long id;
private String review;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof PostComment )) return false;
return id != null && id.equals(((PostComment) o).id);
}
@Override
public int hashCode() {
return 31;
}
}
这样系统就只会产生4条SQL语句:
insert into post (title, id)
values ('First post', 1)
insert into post_comment (post_id, review, id)
values (1, 'My first review', 2)
insert into post_comment (post_id, review, id)
values (1, 'My second review', 3)
insert into post_comment (post_id, review, id)
values (1, 'My third review', 4)
删除一条从表记录
PostComment comment1 = post.getComments().get( 0 );
post.removeComment(comment1);
系统也只会执行1条SQL语句:
delete from post_comment where id = 2