1、 對象的狀態
<1>瞬時對象是new出來的,與Session和數據庫都無關;
<2>持久對象是放入Session中,與Session有關的,Hibernate可以檢測到,更新對象的值,可以影響到數據庫中的值;
<3>脫管對象是在存入數據庫,session關閉的時候由持久對象變換過來的,因此它只與數據庫有關,因此Hibernate檢測不到,數據庫要更新需要更新語句update。
<4>Hibernate只能檢測到Session中的對象變化情況。
<5>當不知道對象是瞬時的還是脫管的,如果要保存或更新數據庫中的值,這個時候就需要用到saveOrUpdate(),讓Hibernate去判斷該對象是什麼狀態。
2、 HQL和Criteria
<1>、HQL查詢(官方推薦):
String hql = "from User as user where user.name=?";
Query query = session.createQuery(hql);
query.setString(0, name);
List<User> list = query.list(); //如果有多條記錄,用list
User u = (User)query.uniqueResult();//確定查到結果集只有一條記錄錄時使用
對於上面的hql語句,我們可以這樣寫(爲name取別名):
String hql = "from User as user where user.name=:n";
query.setString(“n”, name);
Hibernate中的分頁可以用以下語句:
query.setFirstResult(100); //從哪一條開始查詢
query.setMaxResults(20); //每頁顯示多少條
<2>、Criteria條件查詢(比較常用,功能有限):
Criteria c = session.createCriteria(User.class);
c.add(Restrictions.eq(“name”,name)); //從數據庫中查出等於name數據
c.add(Restrictions.lt(“birthday”,new Date());//查出小於birthday數據
分頁語句:
c.setFirstResult(0); //從哪一條開始查詢
c.setMaxResults(10); //每頁顯示多少條
List<User> list = c.list(); //如果有多條記錄,用list
User u = (User)c.uniqueResult();//確定查到的結果集只有一條記錄時使用
<3>、外置命名查詢(很少用)
在實體映射文件的<class>標籤後加上如下配置: <!-- 外置命名查詢(例子:TestOutName) --> <!-- <query name="queryUser"> <![CDATA[from User u where u.id>?]]> </query> 調用時如下: Session session = HibernateUtil.getSession(); Query query = null; session.beginTransaction(); query = session.getNamedQuery("queryUser"); List<User> urs = query.setParameter(0, 5).list(); for(User u : urs) { System.out.println("id:"+u.getId()+" name:"+u.getName()+" createTime:"+u.getCreateTime()); session.getTransaction().commit();
|
<4>、過濾器(很少用)
過濾器配置如下:
在<class>標籤中加入如下代碼: <filter name="idFilter" condition="id >:uid"></filter> 在<class>標籤外加入如下代碼: <filter-def name="idFilter"> <filter-param name="uid" type="integer"/> </filter-def> |
例子代碼:
session.beginTransaction(); session.enableFilter("idFilter").setParameter("uid", 4); query = session.createQuery(“from User”); List<User> urs = query.list(); for(User u : urs) { System.out.println("id:"+u.getId()+" name:"+u.getName()+" createTime:"+u.getCreateTime()); } session.getTransaction().commit(); |
<5>內、外連接問題
l 內連接
內連接就是滿足Document中的uid等於User的id時,將兩個表的數據連接成類似一張表信息的過程。
from Document d inner join d.user on d.uid=d.user.id
l 外連接
外連接分爲左外連、右外連和全外連。
外連接是將兩個表的信息都一一對應後進行連接,得到結果行數可能是兩錶行數的乘積。下面兩個HQL語句功能相同。
select * from User u,Document d where u.id=d.user.id
select * from User u outter join Document d on u.id = d.user.id
<6>、聚合函數和子查詢
在HQL中*只能出現在count(*)中。
select d.user.name, count(*) from Document d group by d.user having count(*)>1 order by d.user.id";
<7>、Iterator查詢與N+1問題
Session session = HibernateUtil.getSession(); Query query = null; try { session.beginTransaction(); query = session.createQuery("from User u where u.id>=4 and u.id<=6"); List<User> urs = query.list(); for(User u : urs) { System.out.println("id:"+u.getId()+" name:"+u.getName()+" createTime:"+u.getCreateTime()); } //上面通過List查詢過的那些User將會在緩存中存在,當下面的Iterator再查詢的時候,它會先從數據庫查出所有User的ID,然後再用ID從緩存中找,如果緩存中有的話,就從緩存中取,不用向數據庫發select語句。 System.out.println("======================================"); query = session.createQuery("from User"); Iterator<User> iter = query.iterate(); while(iter.hasNext()) { User u = iter.next(); System.out.println("id:"+u.getId()+" name:"+u.getName()+" createTime:"+u.getCreateTime()); } session.getTransaction().commit(); } catch (HibernateException e) { session.getTransaction().rollback(); e.printStackTrace(); } finally { HibernateUtil.closeSession(); } |
<8>、導航查詢
給個例子如下:(利用本對象中另外對象的屬性條件來查詢本對象的信息)
String hql = "from Document d where d.user.name=?"; Session session = HibernateUtil.getSession(); Query query = null; session.beginTransaction(); query = session.createQuery(hql); query.setParameter(0, "user5"); List<Document> ds = query.list(); for(Document d : ds) { System.out.println("id:"+d.getId()+" title:"+d.getTitle()+" content:"+d.getContent()+" createTime:"+d.getCreateTime()); |
<9>、HQL中的DML(很少用)
hql的DML語句不受緩存管理,所以很少使用
示例代碼:
3、 Hibernate中CURD的模板代碼如下:
4、 Hibernate中對象狀態圖
flush()可以清除臨時緩存,以保證執行的順序。
evict()可以將對象從緩存中剔除,使其從持久態變爲脫管態。
clear()可以將緩存中的所有對象剔除。
lock()可以爲某對象加鎖機制。