1. 程式人生 > >jpa級聯操作詳解1-級聯儲存(CascadeType.PERSIST)

jpa級聯操作詳解1-級聯儲存(CascadeType.PERSIST)

不論是對於jpa或者是hibernate來說欄位的資料庫對映都不是難點,而是很多初學者都對jpa級聯操作等一系列的東西不大明白,在這一系列的文章中我通過簡單的java實體物件來與大家共同理解jpa(hibernate做實現產品)的級聯操作等難點知識,希望能夠共同提高。為了保證簡單易懂,本系列文章避免光講理論知識,而忽視實際動手,在下面的例子中都有簡單易懂的例子,為了加深理解大家也可以在自己的機器上除錯。同時為了方便理解本系列文章採用對比講解,能讓人一目瞭然。同時歡迎大家共同探討,一起完善這教程
jpa級聯操作詳解1(cascade) 之 cascade={CascadeType.PERSIST}
onetomany 一對多關聯 實體bean:汽車和車庫

(一)
Java程式碼  收藏程式碼
package com.hibernate.jpa.bean1;  

import javax.persistence.Entity;  
import javax.persistence.GeneratedValue;  
import javax.persistence.Id;  
import javax.persistence.JoinColumn;  
import javax.persistence.ManyToOne;  
@Entity  
public class Auto {  

    /** 
     * one to many 一對多關聯 
     */
private Integer autoId; private String autotype; private String autonum; private Garage garage; @Id @GeneratedValue public Integer getAutoId() { return autoId; } public void setAutoId(Integer autoId) { this.autoId = autoId; } public
String getAutotype() { return autotype; } public void setAutotype(String autotype) { this.autotype = autotype; } public String getAutonum() { return autonum; } public void setAutonum(String autonum) { this.autonum = autonum; } @ManyToOne @JoinColumn(name="garageid") public Garage getGarage() { return garage; } public void setGarage(Garage garage) { this.garage = garage; } } ------車庫 package com.hibernate.jpa.bean1; import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.OneToMany; @Entity public class Garage { /** * many to one 多對一 */ private Integer gid; private String garagenum; private Set<Auto> autos = new HashSet<Auto>(); @Id @GeneratedValue public Integer getGid() { return gid; } public void setGid(Integer gid) { this.gid = gid; } @Column(length=20) public String getGaragenum() { return garagenum; } public void setGaragenum(String garagenum) { this.garagenum = garagenum; } @OneToMany(mappedBy="garage") public Set<Auto> getAutos() { return autos; } public void setAutos(Set<Auto> autos) { this.autos = autos; } public void addGarageAuto(Auto auto) { auto.setGarage(this); this.autos.add(auto); } } ---------junit儲存方法 @Test public void save() { EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-hibernate"); EntityManager em = factory.createEntityManager(); em.getTransaction().begin(); Garage garage = new Garage(); garage.setGaragenum("room1"); Auto auto1 = new Auto(); auto1.setAutonum("bj0000"); auto1.setAutotype("car"); Auto auto2 = new Auto(); auto2.setAutonum("bj1231"); auto2.setAutotype("bus"); garage.addGarageAuto(auto1); garage.addGarageAuto(auto2); em.persist(garage); em.getTransaction().commit(); em.close(); factory.close(); }

執行以上save()方法之後,資料庫中只對應的表,但是隻有garage表中被存入了資料,而auto表中沒有被存入資料,僅僅是生成了表而已。
資料庫中的表資料:
+—–+———–+
| gid | garagenum |
+—–+———–+
| 1 | room1 |
+—–+———–+

mysql> select * from auto;
Empty set (0.00 sec)
這兒可以注意到雖然生成了auto資料庫表,但是無法儲存有關auto的資料,因為沒有先儲存auto或設定級聯儲存
觀察發出的sql語句:
Hibernate: insert into Garage (garagenum) values (?)

(二)先儲存auto
將junit測試類中的save方法改為

@Test public void save() {
EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-hibernate");
EntityManager em = factory.createEntityManager();
em.getTransaction().begin();

Garage garage = new Garage();
garage.setGaragenum("room1");

Auto auto1 = new Auto();
auto1.setAutonum("bj0000");
auto1.setAutotype("car");

Auto auto2 = new Auto();
auto2.setAutonum("bj1231");
auto2.setAutotype("bus");

garage.addGarageAuto(auto1);
garage.addGarageAuto(auto2);
em.persist(auto1);
em.persist(auto2);
em.persist(garage);
em.getTransaction().commit();
em.close();
factory.close();
}

觀察發出的sql語句:
Hibernate: insert into Auto (autonum, autotype, garageid) values (?, ?, ?)
Hibernate: insert into Auto (autonum, autotype, garageid) values (?, ?, ?)
Hibernate: insert into Garage (garagenum) values (?)
Hibernate: update Auto set autonum=?, autotype=?, garageid=? where autoId=?
Hibernate: update Auto set autonum=?, autotype=?, garageid=? where autoId=?
當然也生成了對應的資料記錄,但是對資料庫進行了5次操作

mysql> select * from garage;
+-----+-----------+
| gid | garagenum |
+-----+-----------+
| 1 | room1 |
+-----+-----------+

mysql> select * from auto;
+--------+---------+----------+----------+
| autoId | autonum | autotype | garageid |
+--------+---------+----------+----------+
| 1 | bj0000 | car | 1 |
| 2 | bj1231 | bus | 1 |
+--------+---------+----------+----------+
-----------------------------------------------------------------------

(三)設定cascade={CascadeType.PERSIST}
當把
@OneToMany(mappedBy=”garage”)
public Set getAutos() {
return autos;
}
改為:
@OneToMany(cascade={CascadeType.PERSIST} ,mappedBy=”garage”)
public Set getAutos() {
return autos;
}
即多添加了一行cascade={CascadeType.PERSIST} 申明級聯級聯儲存
刪除前面生成的資料庫表garage 和 auto
再次執行save()方法
這是我們看到資料庫中都有對應的記錄
+—–+———–+
| gid | garagenum |
+—–+———–+
| 1 | room1 |
+—–+———–+

+——–+———+———-+———-+
| autoId | autonum | autotype | garageid |
+——–+———+———-+———-+
| 1 | bj0000 | car | 1 |
| 2 | bj1231 | bus | 1 |
+——–+———+———-+———-+
觀察發出的sql語句:
Hibernate: insert into Garage (garagenum) values (?)
Hibernate: insert into Auto (autonum, autotype, garageid) values (?, ?, ?)
Hibernate: insert into Auto (autonum, autotype, garageid) values (?, ?, ?)