【JPA 級聯儲存/串聯刪除】@OneToMany (雙向) 一對多【轉】

來源:互聯網
上載者:User

標籤:tab   bdd   main   提醒   構造   foreign   mit   join   一般來說   

【http://blog.sina.com.cn/s/blog_625d79410101dbdd.html】

  看過前兩篇協助文檔 【JPA】 @OneToOne 單向 和 【JPA】@OneToOne 雙向 想必大家對級聯操作已經充滿了好奇和期待吧。那麼本文將會想大家介紹JPA的級聯儲存操作。在此之前,我希望你能先看下這篇文檔,對級聯注釋的各個屬性有一個大概的瞭解。傳送門:【JPA】 級聯標籤的解釋 @Cascade      在生活中,有許多關係都是一對多的。School(學校)和 Studnet(學生) 之間的關係就是典型的一對多關聯性。一所學校,有多名學生。但是一個學生,只能屬於一所學校。在這裡,我們將這個關係設定為一個雙向的關係。也就說,通過學生實體,我們可以得到他就讀的學校的實體。同樣,通過一個學校實體,我們也可一得到在這所學校就讀的學生實體的集合。 --------< 例 子 >---------------------------------------------------------------------------------------------------------- //學生Model , 這個雙向一對多關聯性的維護端。一般來說,在雙向一對多關聯性中,"多"這一端,一般都是關係的維護端。@Entity@Table(name = "student")public class Student {    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    private Long id;     //在表中建立外鍵 "school_fk"        @ManyToOne    @JoinColumn(name="school_fk")    private School school;   //省略若干get / set}  @Entity@Table(name = "school")public class School {    @Id    @GeneratedValue(strategy = GenerationType.AUTO)    private Long id;     @OneToMany(mappedBy="shcool")    //設定 :級聯 儲存/建立 操作 。建立 學校和學生 的時候,儲存建立的學校那麼建立的學生也同時被儲存    @Column(cascade={CascadeType.PERSIST})    private List students;     //手動構造新增學生的方法    public void addStudent(Strudent stu){            if(stu != null){                 students.add(stu);            }    } //省略若干get / set}-----------------------------------------------------< 測試方法 >--------------------------------------------------------------public class Test(){     public void testCreate(){         School school = new School();         school.setName("學校");          Student st1 = new Student();         st1.setName("學弟");         st1.setSchool(school);         studnetDAO.save(st1);                Student st2 = new Student();         st2.setName("學長");         st2.setSchool(school);         studnetDAO.save(st2);          //新增學生         school.addStudent(st1);         school.addStudent(st2);         schoolDAO.save(school);        //以上的儲存方法並不是級聯儲存操作。我們在學校實體上設定了,級聯儲存操作。        //我們希望JPA這樣做,在建立學校,建立多名學生時。只要將學生的所屬學校設定完成後,儲存學校,即可儲存 所屬該校的學生。    }     //級聯儲存,測試方法    public void testPersistCreateSchool(){            //級聯儲存示範:已經在學校(School)Model 中添加了 級聯儲存操作:cascade={CascadeType.PERSIST}                School school = new School();         school.setName("學校");          Student st1 = new Student();         st1.setName("學弟");         st1.setSchool(school);         //  不需要顯示儲存學生 st1         //studnetDAO.save(st1);                 Student st2 = new Student();         st2.setName("學長");         st2.setSchool(school);         //  不需要顯示儲存學生 st2         //studnetDAO.save(st2);          //新增學生         school.addStudent(st1);         school.addStudent(st2);         schoolDAO.save(school);// 儲存學校,學校內建立的學生也[st1、st2]被儲存了。(級聯儲存)    }     //測試刪除    public void testDeleteSchool(){            //革命第一步,建立學校。            testCreate();            schoolDAO.delete(school);//後台報錯            //avax.persistence.RollbackException: Error while commiting the transaction Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key constraint...                           //之前我們已經知道,想要刪除關係的被維護端,必須先從維護端解除關係。才能正常刪除。所以我們要做的就是,先從 學生端,解除關係。            List<Strudnet> students = school.getStudentList();        for(int i=0;i<students.size();i++){                Student stu = students.get(i);                stu.setSchool(null);//手動從學生實體解除掛系        }        schoolDAO.delete(school);//現在,學校被正常的刪除了。該校的兩名學生資訊依然儲存在資料庫中。只是,他們沒有所屬學校了。         //看到這裡,你一定會責備我。JPA不是很強大嗎?不是很靈活多變嗎?不是很神奇嗎?        //為什麼刪除一個實體,還需要迴圈解除關係,這麼繁瑣的操作?!        //其實,我們有方法可以直接刪除學校。並且,不需要進行這種迴圈從學生實體解除關係的操作。但是,相信我,這種方法你可能不會接受。下面,就讓我們來看看JPA的串聯刪除。        //修改學校的Model 中,在校生欄位()的注釋:@Column(cascade={CascadeType.PERSIST})        //改為: @Column(cascade={CascadeType.PERSIST,CascadeType.REMOVE}) 添加串聯刪除操作。那麼,現在你就可以直接調用刪除學校的方法了。        schoolDAO.delete(school);//現在,學校也被正常刪除了。但是,接下來的一幕,你可能不願意看到。        Stduent stu = studentDAO.findByName(學長");        //列印的結果為: null   是的,你沒看錯。該校所有的學生也被串聯刪除了...        //此時,你應該對JPA的串聯刪除有所理解了。它刪除的對象是實體。級聯指的是級聯實體。如果,在學生的Model 中添加了一個串聯刪除的操作,那麼刪除一個學生,那這個學生所屬的學校也會被刪除掉。        //所以,在這裡,我要提醒你。級聯的刪除操作要慎用。因為,他的破壞性太大了。串聯刪除的操作,並不是針對某個欄位,而是它所管理的實體。}               //測試刪除        public void testDeleteStudent(){        //建立學校和學生        testCreate();        studentDAO.delete(st1);//此時,st1(建立時,名字叫“學弟”的學生)已經被從資料庫中刪除了。但是,他所屬的學校並沒受影響。只不過,st1已經從 學校的 學生集合裡刪除了。這都是由JPA來完成的。         //現在,我們假設:我們沒有執行剛才那部。st1沒有被刪除。學校依然擁有兩名學生。        //在,Stuent的Model 中添加串聯刪除的操作。@JoinColumn(name="school_fk",cascade={CascadeType.REMOVE})   並且,School 的 Model中也添加串聯刪除的操作。        //此時,資料庫中,只有一所學校和兩名學生的資訊。        studentDAO.delete(st1);        //哇,全世界都乾淨了。如果這個時候查看資料庫。你會發現,所有的資料都沒了。為什麼會這樣呢?        //讓我們來看看JPA都幹了什麼:        1:刪除 st1        2:school 被 st1 串聯刪除        3:st2 被 school 串聯刪除        //所以,你才會發現,資料庫中所有的資訊都消失了。當然,如果之前,資料庫中還有別的學校和別的學校所屬學生。那麼它們的資訊是不受影響的。       //羅嗦了這麼多,我感到很抱歉。我只是想提醒你,一定要慎用這個級聯的刪除操作。千萬不用在建立Model 的時候,順手添加一個級聯儲存 刪除之類的操作。一定要根據自己的需求。和操作的實際效果,仔細斟酌之後,再付諸於行動。否則,你直接來個CascadeType.ALL 大多數情況下,它帶給你的都是痛苦的回憶。        }//省略main 方法}

 

【JPA 級聯儲存/串聯刪除】@OneToMany (雙向) 一對多【轉】

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.