Java SSH Hibernate中查詢的方法小結
- 具備一個直觀的、可擴展的條件查詢API是Hibernate的特點。
-
- 15.1. 建立一個Criteria 實例
- org.hibernate.Criteria接口表示特定持久類的一個查詢。Session是 Criteria實例的工廠。
-
- Criteria crit = sess.createCriteria(Cat.class);
- crit.setMaxResults(50);
- List cats = crit.list();
- 15.2. 限制結果集內容
- 一個單獨的查詢條件是org.hibernate.criterion.Criterion 接口的一個實例。org.hibernate.criterion.Restrictions類 定義了得到某些內置Criterion類型的工廠方法。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.like("name", "Fritz%") )
- .add( Restrictions.between("weight", minWeight, maxWeight) )
- .list();
- 約束能夠按邏輯分組。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.like("name", "Fritz%") )
- .add( Restrictions.or(
- Restrictions.eq( "age", new Integer(0) ),
- Restrictions.isNull("age")
- ) )
- .list();
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )
- .add( Restrictions.disjunction()
- .add( Restrictions.isNull("age") )
- .add( Restrictions.eq("age", new Integer(0) ) )
- .add( Restrictions.eq("age", new Integer(1) ) )
- .add( Restrictions.eq("age", new Integer(2) ) )
- ) )
- .list();
- Hibernate提供了至關多的內置criterion類型(Restrictions 子類), 可是尤爲有用的是能夠容許你直接使用SQL。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", Hibernate.STRING) )
- .list();
- {alias}佔位符應當被替換爲被查詢實體的列別名。
-
- Property實例是得到一個條件的另一種途徑。你能夠經過調用Property.forName() 建立一個Property。
-
- Property age = Property.forName("age");
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.disjunction()
- .add( age.isNull() )
- .add( age.eq( new Integer(0) ) )
- .add( age.eq( new Integer(1) ) )
- .add( age.eq( new Integer(2) ) )
- ) )
- .add( Property.forName("name").in( new String[] { "Fritz", "Izi", "Pk" } ) )
- .list();
- 15.3. 結果集排序
- 你可使用org.hibernate.criterion.Order來爲查詢結果排序。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.like("name", "F%")
- .addOrder( Order.asc("name") )
- .addOrder( Order.desc("age") )
- .setMaxResults(50)
- .list();
- List cats = sess.createCriteria(Cat.class)
- .add( Property.forName("name").like("F%") )
- .addOrder( Property.forName("name").asc() )
- .addOrder( Property.forName("age").desc() )
- .setMaxResults(50)
- .list();
- 15.4. 關聯
- 你可使用createCriteria()很是容易的在互相關聯的實體間創建 約束。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.like("name", "F%")
- .createCriteria("kittens")
- .add( Restrictions.like("name", "F%")
- .list();
- 注意第二個 createCriteria()返回一個新的 Criteria實例,該實例引用kittens 集合中的元素。
-
- 接下來,替換形態在某些狀況下也是頗有用的。
-
- List cats = sess.createCriteria(Cat.class)
- .createAlias("kittens", "kt")
- .createAlias("mate", "mt")
- .add( Restrictions.eqProperty("kt.name", "mt.name") )
- .list();
- (createAlias()並不建立一個新的 Criteria實例。)
-
- Cat實例所保存的以前兩次查詢所返回的kittens集合是 沒有被條件預過濾的。若是你但願只得到符合條件的kittens, 你必須使用returnMaps()。
-
- List cats = sess.createCriteria(Cat.class)
- .createCriteria("kittens", "kt")
- .add( Restrictions.eq("name", "F%") )
- .returnMaps()
- .list();
- Iterator iter = cats.iterator();
- while ( iter.hasNext() ) {
- Map map = (Map) iter.next();
- Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
- Cat kitten = (Cat) map.get("kt");
- }
- 15.5. 動態關聯抓取
- 你可使用setFetchMode()在運行時定義動態關聯抓取的語義。
-
- List cats = sess.createCriteria(Cat.class)
- .add( Restrictions.like("name", "Fritz%") )
- .setFetchMode("mate", FetchMode.EAGER)
- .setFetchMode("kittens", FetchMode.EAGER)
- .list();
- 這個查詢能夠經過外鏈接抓取mate和kittens。 查看第 19.1 節 「 抓取策略(Fetching strategies) 」能夠得到更多信息。
-
- 15.6. 查詢示例
- org.hibernate.criterion.Example類容許你經過一個給定實例 構建一個條件查詢。
-
- Cat cat = new Cat();
- cat.setSex('F');
- cat.setColor(Color.BLACK);
- List results = session.createCriteria(Cat.class)
- .add( Example.create(cat) )
- .list();
- 版本屬性、標識符和關聯被忽略。默認狀況下值爲null的屬性將被排除。
-
- 你能夠自行調整Example使之更實用。
-
- Example example = Example.create(cat)
- .excludeZeroes() //exclude zero valued properties
- .excludeProperty("color") //exclude the property named "color"
- .ignoreCase() //perform case insensitive string comparisons
- .enableLike(); //use like for string comparisons
- List results = session.createCriteria(Cat.class)
- .add(example)
- .list();
- 你甚至可使用examples在關聯對象上放置條件。
-
- List results = session.createCriteria(Cat.class)
- .add( Example.create(cat) )
- .createCriteria("mate")
- .add( Example.create( cat.getMate() ) )
- .list();
- 15.7. 投影(Projections)、聚合(aggregation)和分組(grouping)
- org.hibernate.criterion.Projections是 Projection 的實例工廠。咱們經過調用 setProjection()應用投影到一個查詢。
-
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.rowCount() )
- .add( Restrictions.eq("color", Color.BLACK) )
- .list();
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.projectionList()
- .add( Projections.rowCount() )
- .add( Projections.avg("weight") )
- .add( Projections.max("weight") )
- .add( Projections.groupProperty("color") )
- )
- .list();
- 在一個條件查詢中沒有必要顯式的使用 "group by" 。某些投影類型就是被定義爲 分組投影,他們也出如今SQL的group by子句中。
-
- 你能夠選擇把一個別名指派給一個投影,這樣可使投影值被約束或排序所引用。下面是兩種不一樣的實現方式:
-
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
- .addOrder( Order.asc("colr") )
- .list();
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.groupProperty("color").as("colr") )
- .addOrder( Order.asc("colr") )
- .list();
- alias()和as()方法簡便的將一個投影實例包裝到另一個 別名的Projection實例中。簡而言之,當你添加一個投影到一個投影列表中時 你能夠爲它指定一個別名:
-
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.projectionList()
- .add( Projections.rowCount(), "catCountByColor" )
- .add( Projections.avg("weight"), "avgWeight" )
- .add( Projections.max("weight"), "maxWeight" )
- .add( Projections.groupProperty("color"), "color" )
- )
- .addOrder( Order.desc("catCountByColor") )
- .addOrder( Order.desc("avgWeight") )
- .list();
- List results = session.createCriteria(Domestic.class, "cat")
- .createAlias("kittens", "kit")
- .setProjection( Projections.projectionList()
- .add( Projections.property("cat.name"), "catName" )
- .add( Projections.property("kit.name"), "kitName" )
- )
- .addOrder( Order.asc("catName") )
- .addOrder( Order.asc("kitName") )
- .list();
- 你也可使用Property.forName()來表示投影:
-
- List results = session.createCriteria(Cat.class)
- .setProjection( Property.forName("name") )
- .add( Property.forName("color").eq(Color.BLACK) )
- .list();
- List results = session.createCriteria(Cat.class)
- .setProjection( Projections.projectionList()
- .add( Projections.rowCount().as("catCountByColor") )
- .add( Property.forName("weight").avg().as("avgWeight") )
- .add( Property.forName("weight").max().as("maxWeight") )
- .add( Property.forName("color").group().as("color" )
- )
- .addOrder( Order.desc("catCountByColor") )
- .addOrder( Order.desc("avgWeight") )
- .list();
- 15.8. 離線(detached)查詢和子查詢
- DetachedCriteria類使你在一個session範圍以外建立一個查詢,而且可使用任意的 Session來執行它。
-
- DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
- .add( Property.forName("sex").eq('F') );
-
- Session session = ....;
- Transaction txn = session.beginTransaction();
- List results = query.getExecutableCriteria(session).setMaxResults(100).list();
- txn.commit();
- session.close();
- DetachedCriteria也能夠用以表示子查詢。條件實例包含子查詢能夠經過 Subqueries或者Property得到。
-
- DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.class)
- .setProjection( Property.forName("weight").avg() );
- session.createCriteria(Cat.class)
- .add( Property.forName("weight).gt(avgWeight) )
- .list();
- DetachedCriteria weights = DetachedCriteria.forClass(Cat.class)
- .setProjection( Property.forName("weight") );
- session.createCriteria(Cat.class)
- .add( Subqueries.geAll("weight", weights) )
- .list();
- 甚至相互關聯的子查詢也是有可能的:
-
- DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.class, "cat2")
- .setProjection( Property.forName("weight").avg() )
- .add( Property.forName("cat2.sex").eqProperty("cat.sex") );
- session.createCriteria(Cat.class, "cat")
- .add( Property.forName("weight).gt(avgWeightForSex) )
- .list();
-
-
- //具體應用
-
- 把HSQL語句用Criteria代替,感受更加美觀一點,並且還支持中文,要是HSQL想支持中文,你得使用佔位符來設置,具體可參照:http://.blogdriver.com//983190.html
-
- 那麼Criteria的用法是這樣的:
-
- public Collection findCriteria(final DetachedCriteria dc, final IPage page) {
- return (List) getHibernateTemplate().execute(new HibernateCallback(){
- public Object doInHibernate(Session session) throws HibernateException, SQLException {
- Criteria c = dc.getExecutableCriteria(session);
-
- page.setTotalCount(((Integer) c.setProjection(Projections.rowCount()).uniqueResult()).intValue());
- c.setProjection(null);
- c.setResultTransformer(Criteria.ROOT_ENTITY);
- c.setFirstResult(page.getBeginIndex());
- c.setMaxResults(page.getPageSize());
- return c.list();
- }
- }, true);
- }
-
- 其中的參數true表示要Spring強制傳入SessionImpl,而不是傳入Proxy代理類,page.setTotalCount(((Integer) c.setProjection(Projections.rowCount()).uniqueResult()).intValue());
- c.setProjection(null); 目的是爲了得到行數,並設置投影爲空,爲的是返回List出來,若是不設置setProjection(null)的話,c.list將返回的是行數(int型),而不是所要查詢的數據庫信息。可是Criteria的ResultTransformer會變成PassThroughResultTransformer,criteria.list的時候可能結果會跟理想的不同。因此咱們還要再c.setResultTransformer(Criteria.ROOT_ENTITY);把結果以Entity的形式返回,而不是Object[]的形式返回。具體的ResultTransformer能夠google一下。
-
- 測試代碼以下:
-
- public void testCriteria() {
- DetachedCriteria dc = DetachedCriteria.forClass(User.class);
- dc.add(Restrictions.eq("name", "user")).add(Restrictions.like("description", "%主管人員%"));
- IPage page = new Page();
- page.setCurrentPage(1);
- page.setPageSize(10);
- Collection list = _userDAO.findCriteria(dc, page);
- assertNotNull(list);
- assertEquals(1, list.size());
- }
歡迎關注本站公眾號,獲取更多信息