1. 程式人生 > >《Java從入門到放棄》入門篇:hibernate中的多表對應關系(二)

《Java從入門到放棄》入門篇:hibernate中的多表對應關系(二)

文件中 nas join upx proxy n2n pla sta int

前一篇講完了一對多的關系,通過與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

當通過Sessionsave()update()saveOrUpdate()方法來保存或更新當前對象時,級聯保存關聯的臨時對象,並且級聯更新所有關聯的遊離對象

delete

當通過Sessiondelete()方法刪除當前對象時,會級聯刪除關聯的對象

all

包含save-updatedelete的行為

delete-orphan

刪除和當前對象解除關聯關系的所有對象。 即當一個節點在對象圖中成為孤兒節點時,刪除該節點

all-delete-orphan

包含alldelete-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中的多表對應關系(二)