Spring Boot中@OneToMany與@ManyToOne幾個需要注意的問題

來源:互聯網
上載者:User

標籤:spring boot

@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


但是使用這樣同時使用@OneToMany和@ManyToOne要注意以下幾點:

1. 在從表@ManyToOne中要使用FetchType.LAZY,否則會導致效能降低。

2. 主表中增加了2個方法,addComment和removeComment。

3. 從表重載了equals和hashCode方法。

4. 在使用Json來序列化對象時,會產生無限遞迴(Infinite recursion)的錯誤。這裡有2個解決方案:

   a. 在@ManyToOne下面使用@JsonIgnore.

   b. 在@OneToMany下面使用@JsonManagedReference,在@ManyToOne下面使用@JsonBackReference

@JsonBackReference和@JsonManagedReference:@JsonBackReference標註的屬性在序列化(serialization)時,會被忽略。@JsonManagedReference標註的屬性則會被序列化。在序列化時,@JsonBackReference的作用相當於@JsonIgnore,此時可以沒有@JsonManagedReference。但在還原序列化(deserialization)時,如果沒有@JsonManagedReference,則不會自動注入@JsonBackReference標註的屬性;如果有@JsonManagedReference,則會自動注入@JsonBackReference標註的屬性。  


@JsonIgnore:直接忽略某個屬性,以斷開無限遞迴,序列化或還原序列化均忽略。當然如果標註在get、set方法中,則可以分開控制,序列化對應的是get方法,還原序列化對應的是set方法。


本文出自 “隨手筆記” 部落格,轉載請與作者聯絡!

Spring Boot中@OneToMany與@ManyToOne幾個需要注意的問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.