hibernate幾個方法的解釋

(2)session.merge ()方法

該方法將修改表中記錄,其所需要的實體狀態爲脫管狀態,但是注意,它並不影響調用方法前後的狀態,也即該實體依然是脫管狀,見例6.4。

例6.4:session.merge ()方法對狀態的變化

     public void run() {

          //創建UserInfo實例

          UserInfo userInfo = new UserInfo();

          //使之成爲脫管狀態

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //創建UserInfo實例

          UserInfo userInfo2 = new UserInfo();

          //使之成爲脫管狀態

          userInfo2.setId(11112);

          userInfo2.setName("RW4");

          userInfo2.setSex("F");

          //啓動Session

          Session session = HibernateSessionFactory.currentSession();

          //啓動事務

          Transaction tx = session.beginTransaction();

          //調用merge方法,此時UserInfo實體狀態並沒有被持久化

          session.merge(userInfo);

          //調用merge方法,此時UserInfo實體狀態並沒有被持久化

          //但是數據庫中的記錄被更新了

          ①session.merge(userInfo2);

          //merge方法與update方法的差別在於針對同樣的操作update方法會報錯

          //原因在於update方法使得實體狀態成爲了持久化狀態,而Session中不允許兩個持久化實體有同樣的持久化標識

          ②//session.update(userInfo);

          //session.update(userInfo2);

         //以下兩句不會發送SQL,因爲userInfo2不是持久化狀態的實體

         ③userInfo2.setName("RW5");

          userInfo2.setSex("M");

          //提交事務

          tx.commit();

          //關閉Hibernate Session

          HibernateSessionFactory.closeSession();

     }

針對該段代碼將執行如下SQL語句:

Hibernate:

/* ①session.merge(userInfo2)的動作 */

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

Hibernate:

/* ①session.merge(userInfo2)的動作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

session.merge()方法會首先發送一句select語句,去數據庫端獲取UserInfo持久化標識所對應的表記錄;然後自動生成一個持久化狀態的UserInfo實體,與脫管狀態的UserInfo實體做比較是否有所改變;一旦發生了改變,纔會發送update語句執行更新。而按執行順序,若兩句session.merge()方法針對同一個脫管狀態的UserInfo實體,那其結果只會執行最後一個session.merge()方法所發出的update語句。即使執行了session.merge()方法,UserInfo實體依然是脫管狀態,因此③userInfo2. setName("RW5")的語句不會同步數據庫中的表。

(3)session.lock()方法

他爲了解決事務處理而使用,它會將實體從脫管狀態轉變爲持久化狀態。但是值得注意的是,調用session.lock()方法後,脫管狀態的實體信息不會同步到數據庫,而是會從數據庫中返回該持久化狀態。即使在脫管狀態對實體屬性進行了修改,一旦調用了session.lock()方法,這種修改就成了無效,見例6.5。

例6.5:session.lock()方法對狀態的變化

     public void run() {

          //創建UserInfo實例

          UserInfo userInfo = new UserInfo();

          //使之成爲脫管狀態

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //啓動Session

          Session session = HibernateSessionFactory.currentSession();

          //啓動事務

          Transaction tx = session.beginTransaction();

         //發送select獲取數據庫中的當前記錄(執行的SQL根據LockMode不同有不同的方式)

         //UserInfo實體將從脫管狀態轉變爲持久化狀態

          ①session.lock(userInfo,LockMode.UPGRADE_NOWAIT);

          //對當前UserInfo實體進行更新將同步數據庫中的記錄

          ②userInfo.setName("RW8");

          //提交事務

          tx.commit();

          //關閉Hibernate Session

          HibernateSessionFactory.closeSession();

     }

針對該段代碼將執行如下SQL語句:

Hibernate:

/* ①session.lock(userInfo,LockMode.UPGRADE_NOWAIT)的動作 */

select

        id

    from

        userinfo

    where

        id =? for update

            nowait

Hibernate:

/*②userInfo.setName("RW8")的動作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

session.lock()方法並不是爲了將脫管狀態的對象轉變爲持久化狀態,而是爲了事務處理。

(4)session.saveOrUpdate()方法

它是Hibernate提供的既可以新增也可以更新的方法,該方法使實體狀態從脫管或瞬時直接變成持久化。session.saveOrUpdate()方法對實體的持久化標識非常敏感。當實體持久化標識存在,就會發送update SQL,當持久化標識不存在,就會發送insert SQL,見例6.6。

例6.6:session.saveOrUpdate()方法對狀態的變化

     public void run() {

          //創建UserInfo實例

          UserInfo userInfo = new UserInfo();

          //使之成爲脫管狀態

          userInfo.setId(11112);

          userInfo.setName("RW3");

          userInfo.setSex("M");

          //創建UserInfo實例,其爲瞬時狀態

          UserInfo userInfo2 = new UserInfo();

          userInfo2.setName("RW3");

          userInfo2.setSex("M");

          //啓動Session

          Session session = HibernateSessionFactory.currentSession();

          //啓動事務

          Transaction tx = session.beginTransaction();

          //UserInfo存在持久化標識,因此爲新增,從瞬時狀態成爲持久化狀態

          ①session.saveOrUpdate(userInfo2);

          //同步數據庫表記錄

          ②userInfo2.setName("RW9");

          //UserInfo存在持久化標識,因此爲修改,從脫管狀態成爲持久化狀態

          ③session.saveOrUpdate(userInfo);

          //同步數據庫表記錄

          ④userInfo.setName("RW10");

          //提交事務

          tx.commit();

          //關閉Hibernate Session

          HibernateSessionFactory.closeSession();

     }

針對該段代碼將執行如下SQL語句:

Hibernate:

/* ①session.saveOrUpdate(userInfo2)的動作 */

insert

        into

            userinfo

            (NAME, SEX, roomid, id)

        values

            (?, ?, ?, ?)

Hibernate:

/* ②session.saveOrUpdate(userInfo)的動作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

Hibernate:

/* ③session.saveOrUpdate(userInfo)的動作 */

update

            userinfo

        set

            NAME=?,

            SEX=?,

            roomid=?

        where

            id=?

根據代碼的執行,對同一持久化UserInfo屬性需要改變多次,那隻會以最後的屬性爲準,因此③session.saveOrUpdate(userInfo)和④userInfo.setName("RW10")雖然從理論上需要發送兩句update SQL到數據庫,但其實只會產生一句。

(5)session.createQuery()方法

它爲HQL語句調用,HQL(HibernateQusery Language)是Hibernate框架自定義的一種面向對象的語言,類似SQL語言,用以與數據庫進行交互。Hibernate將HQL解析成SQL語句與數據庫交互。HQL被執行後,其所關係到的實體對象將從瞬時狀態轉變爲脫管狀態,見例6.7。

例6.7:session.createQuery()方法對狀態的變化

//一個內部類,作爲SQL查詢的參數傳遞

     class RoomDTO {

          Long id;

          public Long getId() {

               return id;

          }

          public void setId(Long id) {

               this.id = id;

          }

     }

    

     public void run() {

          // 創建一個JavaBean作爲參數傳遞

          RoomDTO roomDTO = new RoomDTO();

          //設置id屬性的值

          roomDTO.setId(1L);

          // 啓動Session

          Session session = HibernateSessionFactory.currentSession();

          // 啓動事務

          Transaction tx = session.beginTransaction();

          //session.createQuery方法作爲HQL查詢的執行

          //其中setProperties方法作爲":id"的參數傳遞,要求roomDTO實例中必須包含id

          //屬性和getId、setId方法

          //由於SQL中包含有3個實體:room、room.id、userinfo,因此返回的結果將是對象數組

          ①Iterator i = session

                    .createQuery(

                              "select room, room.id, userinfo from Room room, UserInfo userinfo where room.id = userinfo.room.id and room.id = :id")

                    .setProperties(roomDTO).iterate();

          //通過迭代將3個實體對象轉型,得到最終結果

          //其中Room實體和UserInfo實體對應的實體狀態爲脫管,roomid則爲一個Long類型

          while (i.hasNext()) {

               //獲取對象數組轉型

               Object[] object = (Object[]) i.next();

               //獲取脫管狀態的Room實體

               ②Room roomr = (Room) object[0];

               System.out.println(roomr.getName());

               System.out.println(roomr.getRoomnumber());

               //獲取roomid

               ③Long roomid = (Long) object[1];

               System.out.println(roomid);

               //獲取脫管狀態的UserInfo實體

               ④UserInfo userinfor = (UserInfo) object[2];

               System.out.println(userinfor.getName());

               System.out.println(userinfor.getSex());

          }

          // 提交事務

          tx.commit();

          // 關閉Hibernate Session

          HibernateSessionFactory.closeSession();

     }

針對該段代碼將執行如下SQL語句:

Hibernate:

/* 執行

①select

        room,

        room.id,

        userinfo

    from

        Room room,

        UserInfo userinfo

    where

        room.id = userinfo.room.id

        and room.id = :id

的HQL語句 */

select

            room0_.id as col_0_0_,

            room0_.id as col_1_0_,

            userinfo1_.id as col_2_0_

        from

            room room0_,

            userinfo userinfo1_

        where

            room0_.id=userinfo1_.roomid

            and room0_.id=?

Hibernate:

/* ②Room roomr = (Room) object[0]的動作(數據庫中有一條記錄,取第一條) */

select

        room0_.id as id1_0_,

        room0_.NAME as NAME1_0_,

        room0_.roomnumber as roomnumber1_0_

    from

        room room0_

    where

        room0_.id=?

Hibernate:

/* ④UserInfo userinfor = (UserInfo) object[2]的動作(數據庫中有兩條記錄,取第一條) */

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

Hibernate:

/* ④UserInfo userinfor=(UserInfo)object[2]的動作(數據庫中有兩條記錄,取第二條)*/

select

        userinfo0_.id as id0_0_,

        userinfo0_.NAME as NAME0_0_,

        userinfo0_.SEX as SEX0_0_,

        userinfo0_.roomid as roomid0_0_

    from

        userinfo userinfo0_

    where

        userinfo0_.id=?

可以看到,Hibernate在執行這段代碼的HQL時,並不會一次性把所有的room表和userinfo表的字段都撈取出來,而是先獲取其主鍵。在之後真正要使用這兩個表所對應的實體對象(Room和UserInfo)時,纔會調用select語句去獲取其所有字段,這是“延時求值”的機制在起作用。session.createQuery()方法不會使實體成爲持久化狀態,因此對Room和UserInfo的實體屬性進行改變不會同步數據庫。

調用createQuery()方法執行HQL時,有多種方式可以傳遞參數,本例提供了一種常見的方式——setProperties()。


說明 除了createQuery()方法外,Hibernate還提供了外置命名查詢(getNameQuery()方法)、結果集過濾(createFilter()方法)、條件查詢(createCriteria()方法)、原生SQL查詢(createSQLQuery()方法)來實現抓取數據。

6.1.6 結語
在本小節中,將對Hibernate中的持久化方法做一個總結,也作爲本問題的結語。

(1)瞬時—脫管狀態的方法有以下幾種。

· 直接將實體的持久化標識進行改變。

· 調用session.createQuery()方法。

· 調用session.getNameQuery()方法。

· 調用session.createFilter()方法。

· 調用session.createCriteria()方法。

· 調用session.createSQLQuery()方法。

(2)瞬時—持久化狀態的方法有以下幾種。

· 調用session.save()方法。

· 調用session.saveOrUpdate()方法。

(3)脫管—持久化狀態的方法有以下幾種。

· 調用session.load()方法。

· 調用session.lock()方法。

· 調用session.update()方法。

· 調用session.saveOrUpdate()方法。

(4)脫管—瞬時狀態的方法有以下幾種。

· 直接將實體的持久化標識清除。

· 調用session.delete()方法。

(5)持久化—脫管狀態的方法:關閉Hibernate Session。

(6)持久化—瞬時狀態的方法。調用session.delete()方法。

(7)脫管狀態-脫管狀態但影響數據庫記錄的方法:調用session.merger()方法。


摘自:http://book.csdn.net/bookfiles/563/10056318681.shtml

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章