hibernate深度學習 遊離狀態 HQL

當我學完這個以後 我彷彿都懂了 = =或許這就是 hibernate的力量吧.

操縱持久化對象(Session)

1.1. 在hibernate中java對象的狀態

Hibernate 把對象分爲 4 種狀態:java

¨       持久化狀態,sql

¨       臨時狀態,數據庫

¨       遊離狀態,數組

¨       刪除狀態.緩存

Session 的特定方法能使對象從一個狀態轉換到另外一個狀態session

 

1.2. 臨時對象(transient)

¨       在使用代理主鍵的狀況下, OID 一般爲 nullapp

¨       不處於 Session 的緩存中函數

¨       在數據庫中沒有對應的記錄測試

 

 

1.2.1.  刪除對象(Removed)

¨       OID 不爲 nullspa

¨       從一個 Session實例的緩存中刪除

¨       Session 已經計劃將其從數據庫刪除, Session 在清理緩存時, 會執行 SQL delete 語句, 刪除數據庫中的對應記錄

¨       通常狀況下, 應用程序不應再使用被刪除的對象

 

1.2.2.  持久化對象(也叫」託管」)(Persist)

1.2.3.   

¨       OID 不爲 null

¨       位於 Session 緩存中

¨       持久化對象和數據庫中的相關記錄對應

¨       Session 在清理緩存時, 會根據持久化對象的屬性變化, 來同步更新數據庫

¨       在同一個 Session 實例的緩存中, 數據庫表中的每條記錄只對應惟一的持久化對象

 

 

1.2.4.  遊離對象(也叫」脫管」)(Detached)

¨       OID 不爲 null

¨       再也不處於 Session 的緩存中

¨       通常狀況需下, 遊離對象是由持久化對象轉變過來的, 所以在數據庫中可能還存在與它對應的記錄

 

1.2.5.  對象的狀態轉換說明(圖)

對象的狀態轉換圖

 

測試hibernatejava對象的狀態

程序代碼

生命週期

狀態

tx = session.beginTransaction();

Customer c = new Customer);

開始生命週期

臨時狀態

Session.save(c)

處於生命週期中

轉變爲持久化狀態

Long id=c.getId();

c = null;

Customer c2 = (Customer)session.load(Customer.class,id);

tx.commit();

處於生命週期中

處於持久化狀態

session.close();

處於生命週期中

轉變爲遊離態

c2.getName();

處於生命週期中

處於遊離態

c2 = null;

結束生命週期

結束生命週期

 

1.2.6.  對象的狀態總結

 

 

Session緩存存在對應的記錄

數據中存在對應的記錄

臨時態

no

no

持久態

yes

可能有也可能沒有

遊離態

no

可能有(數據沒有刪除)也可能沒有

 

1.2.7.  操縱持久化對象的方法(Session中)

1.2.8.  save()

Session 的 save() 方法使一個臨時對象轉變爲持久化對象。

 

¨       Session 的 save() 方法完成如下操做:

  • 把 News 對象加入到 Session 緩存中, 使它進入持久化狀態
  • 選用映射文件指定的標識符生成器, 爲持久化對象分配惟一的 OID. 在使用代理主鍵的狀況下, setId() 方法爲 News 對象設置 OID 使無效的.
  • 計劃執行一條 insert 語句,把Customer對象當前的屬性值組裝到insert語句中

¨       Hibernate 經過持久化對象的 OID 來維持它和數據庫相關記錄的對應關係. 當 News 對象處於持久化狀態時, 不容許程序隨意修改它的 ID

@Test

    public void save() throws Exception{

      

       Session session = sessionFactory.openSession();

   

       Transaction tc = null;

       User user = null;

       try {

           tc = session.beginTransaction();

           user = new User();//臨時狀態

           user.setName("張張");

           session.save(user);//持久化狀態

           tc.commit();

       } catch (Exception e) {

           tc.rollback();

           throw e;

       }finally{

           session.close();

       }

       user.setName("王王");//遊離狀態

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

      

    }

 

1.2.9.      update()

Session 的 update() 方法使一個遊離對象轉變爲持久化對象, 而且計劃執行一條 update 語句。

 

@Test

    public void update() throws Exception{

      

       Session session = sessionFactory.openSession();

   

       Transaction tc = null;

       User user = null;

       try {

           tc = session.beginTransaction();

           user = (User) session.get(User.class, 1);

           //session.clear();

           //session.evict(user);//清楚某一個對象。

           user.setName("馮芬1");

 

           //session.update(user);//執行完才提交給數據庫

           session.flush();//一執行當即提交

           System.out.println("執行");

           tc.commit();

       } catch (Exception e) {

           tc.rollback();

           throw e;

       }finally{

           session.close();

       }

    

  }Session 的 update() 方法使一個遊離對象轉變爲持久化對象, 而且計劃執行一條 update 語句。

 

 

 

若但願 Session 僅當修改了 News 對象的屬性時, 才執行 update() 語句, 能夠把映射文件中 <class> 元素的 select-before-update(更新以前先查詢) 設爲 true. 該屬性的默認值爲 false

 

 

當 update() 方法關聯一個遊離對象時, 若是在 Session 的緩存中已經存在相同 OID 的持久化對象, 會拋出異常

 

緣由是:兩個不一樣的對象擁有相同的OID

 

 

當 update() 方法關聯一個遊離對象時, 若是在數據庫中不存在相應的記錄, 也會拋出異常

 

 

1.2.10.     saveOrUpdate()

該方法同時包含save和update方法,若是參數是臨時對象就用save方法,若是是遊離對象就用update方法,若是是持久化對象就直接返回。

 

斷定對象爲臨時對象的標準

¨       Java 象的 OID 爲 null

¨       映射文件中爲 <id> 設置了 unsaved-value 屬性, 而且 Java 對象的 OID 取值與這個 unsaved-value 屬性值匹配(在hbn3中基本用不到了)

@Test

    public void saveOrUpdate() throws Exception {

       Session session = sessionFactory.openSession();

      

       Transaction tc = null;

       User user = null;

       try {

           tc = session.beginTransaction();

           //臨時對象執行插入

//        user = new User();

//        user.setName("洋洋");

//        session.saveOrUpdate(user);

           //遊離對象執行修改

//        user  = (User) session.get(User.class,1);

//        session.evict(user);

//        session.saveOrUpdate(user);

           //若是是持久化對象就直接返回,不執行操做

           user  = (User) session.get(User.class,1);

           session.saveOrUpdate(user);

          

           tc.commit();

       } catch (Exception e) {

           tc.rollback();

           throw e;

       }finally{

           session.close();

       }

      

    }

 

 

若是參數是臨時對象就會用save方法

 

 

若是是遊離對象就用update方法

若是是持久化對象就直接返回,不執行操做

斷定對象爲臨時對象的標準

¨       Java 對象的 OID 爲 null

¨       映射文件中爲 <id> 設置了 unsaved-value 屬性, 而且 Java 對象的 OID 取值與這個 unsaved-value 屬性值匹配,執行插入操做

 

根據以上判斷臨時對象的標準id=null是臨時對象。但能夠定義屬性爲int  id

* 此時id默認值是0而不是null,應該執行更新操做

* 但實際咱們要執行的插入操做。這時,能夠在id中設置unsaved-value=0(默認值)

 

 

1.2.11.     get()、load()

均可以根據給定的 OID 從數據庫中加載一個持久化對象

@Test

    public void getOrLoad() throws Exception {

       Session session = sessionFactory.openSession();

      

       Transaction tc = null;

       User user = null;

       try {

           tc = session.beginTransaction();

           //get方式會立刻執行sql語句

           user  = (User) session.get(User.class,1);

           System.out.println("aaaaa");

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

           //load方式不會立刻執行sql語句

           user  = (User) session.load(User.class,2);

           System.out.println("bbbbbbbbbbbb");

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

           tc.commit();

       } catch (Exception e) {

           tc.rollback();

           throw e;

       }finally{

           session.close();

       }

      

            }

 

區別:

¨       當數據庫中不存在與 OID 對應的記錄時, load() 方法拋出 ObjectNotFoundException 異常, 而 get() 方法返回 null

¨       二者採用不一樣的延遲檢索策略

get():獲取數據,是持久化狀態

    1. 會生成:select ... where id=?

    2. 會立刻執行sql語句

    3. 若是數據不存在,就返回null

load():獲取數據,是持久化狀態

    1.會生成:select ... where id=?

    2. load()後返回的是一個代理對象,要求類不能是final的,不然不能生成子類代理,就不能使用懶加載功能了。

    3.讓懶加載失效的方式:1、把實體寫成final的;2、在hbm.xml中寫<class ... lazy="false">

    4. 不會立刻執行sql語句,而是在第1次使用非id或class屬性時執行sql

    5. 若是數據不存在,就拋異常:ObjectNotFoundException

 

 

1.2.12.     delete()

Session 的 delete() 方法既能夠刪除一個遊離對象, 也能夠刪除一個持久化對象。

 

¨       若是參數是持久化對象,就執行一個delete語句,若爲遊離對象,先使遊離對象被session關聯,使他變爲持久化對象

¨       計劃執行一條 delete 語句

¨       把對象從 Session 緩存中刪除, 該對象進入刪除狀態.

 

1.2.13.     與觸發器協同工做

Session.save(c);

Session.flush();

Session.refresh(c);

------------------------------------------------------

觸發器的行爲致使緩存與數據庫中的數據不一致。解決辦法是執行完

操做後,當即調用session的flush方法和refresh方法,迫使緩存與

數據庫同步。

Session的update操做方法盲目的激活觸發器

若是遊離狀態的對象的屬性和數據庫一致,則更新操做是多餘的。

爲避免這種狀況:

<class name=「」 table=「」 select-before-update=「true」>

   ……

</class>

1.2.14.     DML(數據操做語言)風格的操做

,Hibernate 提供經過 Hibernate 查詢語言(HQL)來執行大

批量 SQL 風格的 DML 語句的方法。

UPDATE 和 DELETE 語句的僞語法爲:( UPDATE | DELETE ) FROM? EntityName (WHERE

where_conditions)?。

要注意的事項:

•在 FROM 子句(from-clause)中,FROM 關鍵字是可選的

•在 FROM 子句(from-clause)中只能有一個實體名,它能夠是別名。若是實體名是別名,那麼

任何被引用的屬性都必須加上此別名的前綴;若是不是別名,那麼任何有前綴的屬性引用都是

非法的。

•不能在大批量 HQL 語句中使用 joins 鏈接(顯式或者隱式的都不行)。不過在 WHERE 子句中

可使用子查詢。能夠在 where 子句中使用子查詢,子查詢自己能夠包含 join。

•整個 WHERE 子句是可選的。

 

使用 Query.executeUpdate() 方法執行一個 HQL UPDATE語句

由 Query.executeUpdate() 方法返回的整型值代表了受此操做影響的記錄數量

 

Session session = sessionFactory.openSession();

Transaction tx = session.beginTransaction();

String hqlDelete = "delete Customer c where c.name = :oldName";

// or String hqlDelete = "delete Customer where name = :oldName";

int deletedEntities = s.createQuery( hqlDelete )

.setString( "oldName", oldName )

.executeUpdate();

tx.commit();

session.close();

 

6.HQL介紹

 SQL(表和字段)  HQL(對象和屬性)

使用HQL查詢

         HQL: Hibernate Query Language.

         特色:

 1,與SQL類似,SQL中的語法基本上均可以直接使用。

 2,SQL查詢的是表和表中的列;HQL查詢的是對象與對象中的屬性。

 3,HQL的關鍵字不區分大小寫,類名與屬性名是區分大小寫的。

 4,SELECT能夠省略.

案例:

  1,簡單的查詢

                     hql = "FROM Employee";

                     hql = "FROM Employee AS e";   使用別名

                     hql = "FROM Employee e";   使用別名,as關鍵字可省略

 執行查詢

List list = session.createQuery(hql).list();

 

顯示結果

                   

while(itr.hasNext()){

                                     //System.out.println(itr.next().getName());

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

                                     System.out.println(object[0]+":"+object[1]);

                            }

 

 2,帶上過濾條件的(可使用別名):Where

                    

 hql = "FROM Employee WHERE id<10";

                     hql = "FROM Employee e WHERE e.id<10";

                     hql = "FROM Employee e WHERE e.id<10 AND e.id>5";

 

 

3,帶上排序條件的:Order By

             

        hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name";

                     hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC";

                     hql = "FROM Employee e WHERE e.id<10 ORDER BY e.name DESC, id ASC";

 

 

4,指定select子句(不可使用select *)

                  

   hql = "SELECT e FROM Employee e";   至關於"FROM Employee e"

                     hql = "SELECT e.name FROM Employee e";   只查詢一個列,返回的集合的元素類型就是這個屬性的類型

                     hql = "SELECT e.id,e.name FROM Employee e";   查詢多個列,返回的集合的元素類型是Object數組

                     hql = "SELECT new Employee(e.id,e.name) FROM Employee e";   可使用new語法,指定把查詢出的部分屬性封裝到對象中

 

 

5,執行查詢,得到結果(list、uniqueResult、分頁 )

                     

Query query = session.createQuery("FROM Employee e WHERE id<3");

                     query.setFirstResult(0);

                     query.setMaxResults(10);

                     List list = query.list();   查詢的結果是一個List集合

                     Employee employee = (Employee) query.uniqueResult();  查詢的結果是惟一的一個結果,當結果有多個,就會拋異常

                     System.out.println(employee);

 

 

6,函數的使用

hql = "select count(id) from Department";

                            Number num =  (Number) session.createQuery(hql).uniqueResult();

                            System.out.println(num);

 

7,分組查詢

hql = "select d.name,count(d.name) from Department d group by d.name";

hql = "select d.name,count(d.name) from Department d group by d.name having count(d.name)>5";

 

 

 

8,參數查詢

第一種:使用「?」

hql = "from Department d where d.id between ? and ? ";

List list = session.createQuery(hql)

                            .setParameter(0, 2)

                            .setParameter(1, 8)

                            .list();

 

第二種:使用變量名

    

    hql = "FROM Employee e WHERE id BETWEEN :idMin AND :idMax";

                   List list = session.createQuery(hql)//

                   .setParameter("idMax", 15)//

                   .setParameter("idMin", 5)//

         .list();

 

第三種:當參數是集合時,使用setParameterList()設置參數值

             

      hql = "FROM Employee e WHERE id IN (:ids)";

                   List list = session.createQuery(hql)//

                   .setParameterList("ids", new Object[] { 1, 2, 3, 5, 8, 100 })//

                   .list();

 

 

9在映射文件配置HQL語句

爲了使程序具備更大的靈活性,Hibernate能夠在映射文件中配置HQL語句。以下所示爲在Student.hbm.xml中的配置。

<hibernate-mapping>

     <class name="hibernate.ch06.Student" table="student" catalog="joblog">

          <!--此處省略了配置-->

     </class>

     <query name="searchStudent"><![CDATA[

     from Student s where s.sage>22

     ]]><![CDATA[  ]]>表示一些特殊字符不須要轉義)

     </query>

</hibernate-mapping>

 

能夠用以下代碼訪問配置文件中的HQL語句。

        

Session session=HibernateSessionFactory.currentSession();//建立Session

        Query query=session.getNamedQuery("searchStudent");                   //用getNamedQuery獲得查詢

        List list=query.list();                                                   //執行查詢

        Iterator it=list.iterator();

       

        while(it.hasNext()){

               Student stu=(Student)it.next();

               System.out.println(stu.getSname());

        }

 

其中,getNamedQuery()函數用來訪問映射文件Student.hbm.xml中配置的HQL語句,參數爲配置的名稱。

Select s.id,s.name, c.name from t_student s,t_classes c where c.id = s.classId

Select s.id,s.name, c.name from t_student s right join t_classes c on s.classtId = c.id;

10.鏈接查詢

                         

   //第一種:(內鏈接)

                            //hql = "select s.id,s.name,c.name from Student s join s.classes c";

                            //第二種:

                            //hql = "select s.id,s.name,s.classes.name from Student s";

                            //外鏈接:

hql = "select s.id,s.name,c.name from Student s right join s.classes c";

hql = "select s.id,s.name,c.name from Student s left join s.classes c";

 

11.更新

               

             //更新前:

                            Student student = (Student)session.get(Student.class, 2);

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

                            int num = session.createQuery("update Student s set s.name=? where s.id=2")

                            .setParameter(0,"好人1")

                            .executeUpdate();

                            System.out.println(num);

                            //更新後:

                            session.refresh(student);

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

 

12.刪除

                            

/*int num1 = session.createQuery("delete Student s  where s.id=1")

                            .executeUpdate();

                            System.out.println(num1);*/ 

 

 

Criteria查詢方式

// 建立Criteria對象

         Criteria criteria = session.createCriteria(Student.class);

                            // 增長過濾條件

                            criteria.add(Restrictions.ge("id", 2));

                            criteria.add(Restrictions.le("id", 5));

 

                            // 增長排序條件

criteria.addOrder(Order.desc("id"));

                            criteria.addOrder(Order.desc("name"));

                                                        // 執行查詢

                            // criteria.setFirstResult(0);

                            // criteria.setMaxResults(100);

                            // criteria.uniqueResult();

                            // criteria.list()

                            List list = criteria.list();

                            Iterator  itr = list.iterator();

                            while(itr.hasNext()){

                                    

                                     Student student = (Student)itr.next();

                                     System.out.println(student.getName()+":"+student.getScore());

                            }

 寫完了 今天落枕了 起牀也是在牀底睜開眼  歪着脖子寫了折磨一一篇, 真難受啊 不過這質量算是我寫過最棒的一篇了吧.

相關文章
相關標籤/搜索