一、Get/Load
Get方法是立即檢索,而load是延遲檢索,他們都是根據主鍵進行查詢。在<class>標簽中,若把lazy屬性改為false,load方法就會立即檢索,class中的lazy屬性僅對load方法有效。在使用load時,當數據庫沒有找到數據時,會有ObjectNotFoundException,異常。
1 public void LazyTest() { 2 //lazy 改為false或者true,查看打印sql的時機 3 Tb_User u = session.load(Tb_User.class, "1"); 4 //System.out.println(u.getName()); 5 }
二、1-n或多對多的查詢
2.1 set 標簽的lazy屬性 可以設置為三種值:true,false,extra。
select count(ID) from TB_ORDER where userid =?
2.2 set標簽的batch-size屬性,確定批量初始化集合元素的個數
2.3 set標簽的fetch屬性,默認值為select,確定初始化集合的方式
1.select ,通過正常的方式來初始化set
2.subselect,通過子查詢的方式來初始化所有的set集合,lazty屬性有效,batch-size屬性失效,此時sql語句
Hibernate: select orders0_.userid as userid6_0_1_, orders0_.ID as ID1_0_1_, orders0_.ID as ID1_0_0_, orders0_.NAME as NAME2_0_0_, orders0_.MONEY as MONEY3_0_0_, orders0_.COUNT as COUNT4_0_0_, orders0_.CREATETIME as CREATETIME5_0_0_, orders0_.userid as userid6_0_0_ from TB_ORDER orders0_ where orders0_.userid in ( select tb_user0_.ID from TB_USER tb_user0_ )
2.4 join,lazy會失效,采用左外連接查詢。若使用hql查詢,會忽略fetch=join屬性
三、n-1的查詢
1. many-to-one 的 lazy屬性有三個取值:proxy 延遲檢索,no-proxy,false 立即檢索
2.many-to-one 的 fetch屬性有兩個取值:select,join,作用和上面的一樣。
3.batch-size屬性是加到1方的class標簽上的,這裡不是加到many-to-one上的!
四、采用hql查詢
1.使用步驟:
-用過Session的createQuery方法創建一個Query對象,參數為HQL語句
-動態的綁定參數(按參數名字綁定 :參數名,按參數位置綁定 ?)
1 //基於參數位置綁定參數值 2 @Test 3 public void test1(){ 4 Query query = session.createQuery("FROM Tb_User WHERE name = ? AND id = ?"); 5 query.setParameter(0, "1"); 6 query.setParameter(1, "1"); 7 List<Tb_User> list = query.getResultList(); 8 System.out.println(list.size()); 9 } 10 11 //基於參數名稱綁定參數值 12 @Test 13 public void test2(){ 14 Query query = session.createQuery("FROM Tb_User WHERE name = :name AND id = :id"); 15 query.setParameter("name", "1"); 16 query.setParameter("id", "1"); 17 List<Tb_User> list = query.getResultList(); 18 System.out.println(list.size()); 19 }
-調用query相關方法執行查詢語句
2.分頁查詢 兩個相關方法 setFirsetResult | setMaxResult
1 //分頁測試 2 @Test 3 public void pageTest(){ 4 Query query = session.createQuery("SELECT id FROM Tb_User"); 5 int pageNo = 2;//當前頁數 6 int pageSize = 4;//每頁大小 7 8 List<String> list = query 9 .setFirstResult((pageNo - 1) * pageSize) 10 .setMaxResults(4).getResultList(); 11 for(String u : list){ 12 System.out.println(u); 13 } 14 }
3.命名查詢 getNamedQuery
命名查詢可以讓我們在xml中定義hql語句,在映射文件中,class標簽外添加;這裡用CDATA是因為若hql中有大於>或小於<等符號時,可以避免沖突
<query name = "findUserByName"> <![CDATA[FROM Tb_User a WHERE a.name = :name]]> </query>
然後通過name屬性來執行該語句
@Test public void nameQuery(){ Query query = session.getNamedQuery("findUserByName"); List<Tb_User> list = query.setParameter("name", "1").getResultList(); System.out.println(list.size()); }
4.投影查詢 查詢表中某些字段
這裡選擇了兩個字段,因此每條數據查詢出來是一個object數組,由於有多條數據,所以就用了List<Object[]>來保存結果,若只查詢一個字段,則可用List<T>來保存結果
@Test public void filedQuery(){ String hql = "SELECT a.id ,a.name FROM Tb_User a"; Query query = session.createQuery(hql); List<Object[]> result = query.getResultList(); for(Object[] objs: result){ System.out.println(Arrays.asList(objs)); //System.out.println(objs[0]); } }
當然,也可以在查詢出來的同時初始化這個類,如下,注意需要在Tb_User中添加一個只有id和name的構造函數。
@Test public void filedQuery2(){ String hql = "SELECT new Tb_User( a.id ,a.name ) FROM Tb_User a"; Query query = session.createQuery(hql); List<Tb_User> result = query.getResultList(); for(Tb_User u: result){ System.out.println(u); } }
5.報表查詢,hql可用GROUP BY 和 HAVING 關鍵字,可以調用一下的聚集函數
-count()
-min()
-max()
-sum()
-avg()
//查詢每個用戶的最大金額和最小金額 @Test public void GroupQuery(){ String hql = "SELECT min(a.money) ,max(a.money) FROM Tb_Order a "+ "GROUP BY a.user"; Query query = session.createQuery(hql); List<Object[]> result = query.getResultList(); for(Object[] objs: result){ System.out.println(Arrays.asList(objs)); //System.out.println(objs[0]); } }
6.左外連接
左外連接有兩種關鍵字:LEFT JOIN 和 LEFT JOIN FETCH
LEFT JOIN FETCH的方式是查出來,並且立即初始化集合,集合可能包含有重復的元素,需要去重。去重可用hql的distinct或者hashset集合
@Test public void leftJoinFetch() { String hql = "From Tb_User a LEFT JOIN FETCH a.orders"; //String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN FETCH a.orders"; //hql去掉重復的字段 Query query = session.createQuery(hql); List<Tb_User> list = query.getResultList(); //list = new ArrayList<Tb_User>(new LinkedHashSet<Tb_User>(list));//hashset去掉重復字段 for(Tb_User u : list){ System.out.println(u.getName() +"-"+ u.getOrders().size()); } }
LEFT JOIN方式,默認查出來每條數據是一個對象數組,每個對象數組包含了Tb_User和Tb_Order,但是他並沒有初始話集合,初始化集合的操作需要更加映射文件的配置來。可能會有重復,但是只能用hql的distinct關鍵字去重
@Test public void leftJoin() { String hql = "From Tb_User a LEFT JOIN a.orders"; Query query = session.createQuery(hql); List<Object[]> list = query.getResultList(); for(Object[] objs : list){ System.out.println(Arrays.asList(objs)); } }
這下面這種情況下,他會根據user映射文件的配置查詢數據庫得到他order的數量
@Test public void leftJoin2() { String hql = "SELECT DISTINCT a From Tb_User a LEFT JOIN a.orders"; Query query = session.createQuery(hql); List<Tb_User> list = query.getResultList(); for(Tb_User u : list){ System.out.println(u.getName() +"-"+ u.getOrders().size()); } }
內鏈接也有兩個INNER JOIN FETCH 和INNER JOIN 和左外連接的區別在於他不會查詢左表不符合條件的記錄,在這裡即是不返回訂單為0的用戶。
五、QBC(Query By Criteria) 面向對象的查詢
使用Criteria的接口來實現
@Test public void qbcTest(){ //1.創建一個Criteria對象 Criteria criteria = session.createCriteria(Tb_User.class); //2.添加查詢條件 criteria.add(Restrictions.eq("id","1")); //3.執行查詢 Tb_User u = (Tb_User)criteria.uniqueResult(); System.out.println(u); }
他們的and或者or的查詢方式
@Test public void qbcTest2(){ Criteria criteria = session.createCriteria(Tb_User.class); // AND : 使用Conjunction表示 Conjunction conjunction = Restrictions.conjunction(); conjunction.add(Restrictions.like("name","1",MatchMode.ANYWHERE)); conjunction.add(Restrictions.eq("id", "1")); criteria.add(conjunction); System.out.println(criteria.list()); //or Criteria criteria1 = session.createCriteria(Tb_Order.class); Disjunction disjunction = Restrictions.disjunction(); disjunction.add(Restrictions.ge("money",2.0)); disjunction.add(Restrictions.eq("name", "aa")); criteria1.add(disjunction); System.out.println(criteria1.list().size()); }
criteria的統計查詢
@Test public void qbcTest3(){ Criteria criteria = session.createCriteria(Tb_Order.class); //統計查詢:使用prijection來表示 criteria.setProjection(Projections.max("money")); //添加排序 //criteria.addOrder(Order.asc("id")); System.out.println(criteria.uniqueResult()); }
他的分頁和query.getResultList方法是一樣的
六、本地sql查詢
若自己寫sql查詢出來是一個對象數組,使用起來感覺怪怪的。
@Test public void nativeSql(){ String sql = "select * from Tb_User where name = :name"; Query query = session.createSQLQuery(sql); query.setParameter("name", "1"); List<Object[]> list = query.getResultList(); for(Object[] u : list){ System.out.println(Arrays.asList(u)); } }
若要執行其他sql
@Test public void nativeSql(){ UUID u = UUID.randomUUID(); String sql = "insert into Tb_User(id,name) values (:id,:name)"; Query query = session.createSQLQuery(sql); query.setParameter("id", u.toString()); query.setParameter("name", u.toString()); query.executeUpdate(); }
Demo地址:http://pan.baidu.com/s/1kUT9H91