zoukankan      html  css  js  c++  java
  • Hibernate Criterion

    在查询方法设计上能够灵活的依据Criteria的特点来方便地进行查询条件的组装.
    Hibernate设计了CriteriaSpecification作为Criteria的父接口,以下提供了Criteria和DetachedCriteria.

    Criteria和DetachedCriteria的主要差别在于创建的形式不一样,Criteria是在线的,所以它是由HibernateSession进行创建的;
    而DetachedCriteria是离线的,创建时无需Session,DetachedCriteria提供了2个静态方法forClass(Class)或forEntityName(Name)进行DetachedCriteria实例的创建.
    Spring的框架提供了getHibernateTemplate().findByCriteria(detachedCriteria)方法,能够非常方便地依据DetachedCriteria来返回查询结果.
    Criteria和DetachedCriteria均可使用Criterion和Projection设置查询条件.能够设置FetchMode(联合查询抓取的模式),设置排序方式.
    对于Criteria还能够设置FlushModel(冲刷Session的方式)和LockMode(数据库锁模式).

    以下对Criterion和Projection进行具体说明.

    Criterion是Criteria的查询条件.Criteria提供了add(Criterion criterion)方法来加入查询条件.Criterion接口的主要实现包含:Example、Junction和SimpleExpression.
    而Junction的实际使用是它的两个子类conjunction和disjunction,各自是使用AND和OR操作符进行来联结查询条件集合.
    Criterion的实例能够通过Restrictions工具类来创建,Restrictions提供了大量的静态方法;如:eq(等于)、ge(大于等于)、between等来方法的创建Criterion查询条件(SimpleExpression实例).
    除此之外,Restrictions还提供了方法来创建conjunction和disjunction实例,通过往该实例的add(Criteria)方法来添加查询条件形成一个查询条件集合.

    至于Example的创建有所不同,Example本身提供了一个静态方法create(Object entity),即依据一个对象(实际使用中通常是映射到数据库的对象)来创建.然后能够设置一些过滤条件:
    Example exampleUser = Example.create(u)
    .ignoreCase() // 忽略大写和小写
    .enableLike(MatchMode.ANYWHERE); // 对String类型的属性,不管在那里值在那里都匹配.相当于%value% Project主要是让Criteria能够进行报表查询,并能够实现分组.

    Project主要有SimpleProjection、ProjectionList和Property三个实现.
    当中SimpleProjection和ProjectionList的实例化是由内建的Projections来完毕,如提供的avg、count、max、min、sum能够让开发人员非常easy对某个字段进行统计查询.
    Property是对某个字段进行查询条件的设置,如通过Porperty.forName("color").in(new String[]{"black","red","write"});则能够创建一个Project实例.
    通过criteria的add(Project)方法增加到查询条件中去.使用Criteria进行查询,主要要清晰的是Hibernate提供了那些类和方法来满足开发中查询条件的创建和组装,以下介绍几种使用方法:

    1.创建一个Criteria实例
    org.hibernate.Criteria接口表示特定持久类的一个查询.Session是Criteria实例的工厂.
    Criteria crit = sess.createCriteria(Cat.class);
    crit.setMaxResults(50);
    List cats = crit.list();

    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();

    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();

    4.关联
    你能够使用createCriteria()很easy的在互相关联的实体间建立约束.
    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");
    }

    5.动态关联抓取
    你能够使用setFetchMode()在执行时定义动态关联抓取的语义.
    List cats = sess.createCriteria(Cat.class)
    .add(Restrictions.like("name","Fritz%"))
    .setFetchMode("mate",FetchMode.EAGER)
    .setFetchMode("kittens",FetchMode.EAGER)
    .list();
    这个查询能够通过外连接抓取mate和kittens.

    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();

    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();

    8.离线(detached)查询和子查询
    DetachedCriteria类使你在一个session范围之外创建一个查询,而且能够使用随意的session来运行它.

    DetachedCriteria query = DetachedCriteria.forClass(Cat.class)
    .add(Property.forName("sex").eq('F'));
    //创建一个Session
    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();

    补充:
    criteria.add(Expression.eq("status",new Integer(status)));
    criteria.add(Expression.in("status", optParm.getQueryStatus()));

  • 相关阅读:
    hdu 5646 DZY Loves Partition
    bzoj 1001 狼抓兔子 平面图最小割
    poj 1815 Friendship 最小割 拆点 输出字典序
    spoj 1693 Coconuts 最小割 二者取其一式
    hdu 5643 King's Game 约瑟夫环变形
    约瑟夫环问题
    hdu 5642 King's Order
    CodeForces 631C Report
    1039: C语言程序设计教程(第三版)课后习题9.4
    1043: C语言程序设计教程(第三版)课后习题10.1
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4031679.html
Copyright © 2011-2022 走看看