《Java從入門到放棄》入門篇:hibernate中的多表對應關系(二)
前一篇講完了一對多的關系,通過與JDBC對比應該能發現,是不是比JDBC簡單了很多?
我們只需要把對象只間的包含或對應關系理清楚,完全不用我們自己來寫SQL語句。所以使用hibernate框架後,我們的關註重點是業務邏輯,所有的SQL語句都不用再操心了。
上次忘記說明,如果使用增、刪、改的操作,我們還需要再引入一個Transaction對象。代碼如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession(); Transaction tx = session.beginTransaction();
try {
Author author = new Author( "劉皇叔" , "sb250" );
session.save(author);
tx.commit(); //提交
System.out.println( "保存成功" );
} catch (Exception e) {
tx.rollback(); //回滾
} HibernateSessionFactory.closeSession();
}
|
知道數據庫中事務的客官應該對這個對象不陌生吧。所以執行了session對象的增、刪、改後,一定要記得使用transaction對象進行提交。如果某個業務有多次數據的操作,那麽一定記得使用事務。
接下來,我們繼續上次未完成的任務。
二、多一對映射關系
上次我們已經生成了作者和博客表的關系,從作者的角度來看,作者對應博客是一對多,而從博客的角度來看,博客對應作者是多對一。所以博客實體類中的代碼如下:
1 2 3 4 5 6 7 8 9 10 |
public class Blog implements java.io.Serializable {
private Integer id;
private Author author; //相當於數據庫中的外鍵引用
private String title;
private String content;
private Date createTime;
private String type;
//封裝的get和set方法略
}
|
blog的映射文件中代碼如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
< class name = "com.pxy.entity.Blog" table = "blog" catalog = "blogdb" >
< id name = "id" type = "java.lang.Integer" >
< column name = "id" />
< generator class = "native" />
</ id >
< many-to-one name = "author" class = "com.pxy.entity.Author" fetch = "select" >
< column name = "author_id" />
</ many-to-one >
< property name = "title" type = "java.lang.String" >
< column name = "title" length = "30" not-null = "true" />
</ property >
< property name = "content" type = "java.lang.String" >
< column name = "content" length = "500" />
</ property >
< property name = "createTime" type = "java.util.Date" >
< column name = "create_time" length = "10" />
</ property >
< property name = "type" type = "java.lang.String" >
< column name = "type" length = "20" />
</ property >
</ class >
|
裏面的many-to-one就是多對一的關系。我們同樣先不做任何修改,來查詢一篇博客看看效果。
1 2 3 4 5 6 7 8 9 |
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Blog blog = (Blog)session.get(Blog. class , 6 );
System.out.println( "標題:" +blog.getTitle());
System.out.println( "內容:" +blog.getContent());
System.out.println( "作者:" +blog.getAuthor().getUsername());
HibernateSessionFactory.closeSession();
}
|
結果如下:
接下來,我們來聊五毛錢的與映射關系有關的幾個屬性:not-null、fetch、lazy、cascade、inverse。
1)not-null
從名字就能看出來,這個表示非空,不用多說吧。
2)fetch
表示獲取數據的方式,對應的值有兩個:select和join。默認是select。它們的差別我們可以通過生成的SQL語句來看看。
select的結果如上圖,默認只查詢blog的內容,需要使用映射的author時,再次到數據庫中查詢。
我們將Blog的映射文件中many-to-one中的fetch的值設置為join,結果如下圖:
區別是不是很明顯!!!
使用join後,默認就使用多表聯合的方式查詢了所有的數據。
3)lazy
接下來,我們先把fetch的值還原為select。然後再把lazy的分別設置為proxy和false看效果對比。
左圖為設置lazy的值為false(實時加載,實體類中包含的所有對象都一次性查詢出來),
右圖為設置lazy的值為proxy(延時加載,默認只查詢blog的數據,當需要使用其中包含的對象時再去數據庫查詢)。
4)cascade
表示執行增、刪、改時的級聯操作。其值有:none、save-update、delete、delete-orphan、all、all-delete-orphan。
cascade屬性 |
描 述 |
none |
當Session操縱當前對象時,忽略其關聯對象。它是cascade屬性的默認值 |
save-update |
當通過Session的save()、update()及saveOrUpdate()方法來保存或更新當前對象時,級聯保存關聯的臨時對象,並且級聯更新所有關聯的遊離對象 |
delete |
當通過Session的delete()方法刪除當前對象時,會級聯刪除關聯的對象 |
all |
包含save-update、delete的行為 |
delete-orphan |
刪除和當前對象解除關聯關系的所有對象。 即當一個節點在對象圖中成為孤兒節點時,刪除該節點 |
all-delete-orphan |
包含all和delete-orphan的行為 |
接下來,我們演示一下默認值和save-update,其它的值,各位客官可以自行試驗哈。
4.1)不設置cascade屬性
編碼如下代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Transaction tx = session.beginTransaction();
//創建作者和博客對象
Author author = new Author( "劉皇叔" , "sb250" );
Blog blog = new Blog( "論持久戰" );
//相互關聯
author.getBlogs().add(blog);
blog.setAuthor(author);
//保存作者或者保存博客
session.save(author);
//session.save(blog);
//提交數據
tx.commit();
HibernateSessionFactory.closeSession();
}
|
運行後查看結果,可以發現,只添加了作者或者博客(註意看代碼,只添加作者或者只添加博客)。
4.2)把blog的映射文件和author的映射文件中的cascade屬性設置為save-update
Test中的代碼不做任何修改,再次運行看效果。
現在的添加操作就進行了級聯,雖然我們只保存作者,或者只保存博客,但Session發現它內部還包含新的對象時就會級聯更新。
5)inverse
表示是否由關聯對象來主控級聯關系。一般設置在一對多中的”一方“。看4.2圖中的set標簽中包含有inverse屬性。
接下來,我們把inverse設置為false。
是不是發現多了一個update?
其實很好理解,因為把inverse設置為false後,表示沒有主控方了,A執行了控制B的代碼後,B也會再次執行控制A的代碼,所以blog對象會發現:“喲,我還關聯有author對象,那我必須要更新一下它的ID”。
今天的內容雖然簡單,但大夥一定要把每個屬性及每個屬性的值都多練習幾遍,不然很容易弄混效果。
想當初第一次講這個的時候,自己都是暈暈的,快被學生問瘋了···
《Java從入門到放棄》入門篇:hibernate中的多表對應關系(二)