hibernate QBC和QBE精讲与案列分析(上)

转载:http://blog.sina.com.cn/s/blog_7fff746d0101ese2.html

本章的主要内容包括:

● QBC数据检索

 

● 连接查询

● Hibernate的数据检索策略

  QBC数据检索

  Hibernate提供了另一种形式的面向对象的查询方式QBC(Query by Criteria)。这种查询是以函数API的方式动态地设置查询条件,组成查询语句。基本结构是session创建criteria接口,然后调用criteria接口的add函数,增加查询条件(criterion),然后调用criterialist()函数返回查询结果。

  除了有当前session创建的criteria接口外,Hibernate还提供了在session不可用时,组织查询语句的游离态的DetachCriteria类,它的查询条件设置与criteria类似,只是它不由session创建,而是在需要session可用时,再调用getExecutableCriteria()执行查询。

  另外,为了让criteria的查询方法与HQL一样功能丰富,Hibernate还提供了projections类,用于提供各种函数来产生可以使用聚集函数,进行投影查询和进行查询结果设置的各种projection接口,提供了Restrictions类用于提供各种函数来产生各种criterion作为查询条件,提供了用于结果排序的order类。

  图8-1Criteria相关类的结构图。

 

图8-1  Criteria相关类图

  由图8-1可见,Criteria接口和DetachedCriteria类都继承了CriteriaSpecification接口,开发人员在使用QBC查询时,都是直接选择用CriteriaDetachedCriteria。而它们两个都是一样使用可以设置各种查询条件或者查询结果的CriterionProjection等接口。

8.1.1  QBC查询主要类

  下面分别对QBC查询中使用的几个主要接口和类进行介绍。

  1. Criteria接口

  Criteria调用add函数添加Criterion对象来组成查询条件,然后根据查询条件来查询持久化类对象。与HQL查询的Query类一样,也是由Session调用createCriteria()函数创建。

  以下代码是检索价格大于25Product对象。

      Criteria crit = session.createCriteria(Product.class);

          crit.add(Restrictions.gt("price",new Double(25.0)));

          List results = crit.list();

  相应地,HQL实现的代码如下:

          Query query = session.createQuery(

                  "from Product where price>:price");

          query.setDouble("price",25.0);

          List results = query.list();

  使用Criteria查询的步骤是:(ke ruai tie ria)

  (1) 调用一个可用的sessioncreateCriteria()方法创建Criteria对象,其中createCriteria()方法以被查询的实体类类型作为参数。

  (2) 根据需要使用add函数设置各种criterion查询条件,使用setProjection设置projection

  (3) 调用Criterialist或者scroll方法即执行查询语句,检索数据库,把查询结果返回放在ListScrollableResults中。

  (4) 读取ListScrollableResults,即可取出查询对象。

  Criteria接口在调用List或者Scroll方法时执行数据库检索,返回结果可以是以List形式或者ScrollableResults形式,与Query相比,少了iterate()方法执行返回iterator形式的结果。另外,与Query类似,Criteria也可以使用setFlushModesetCacheModesetTimeOut等设置各种Criteria查询的环境,可以使用setFirstResult()setMaxResult()等方法设置检索结果。

  下面介绍在Query中没有的,但在Criteria中使用的主要的函数:

  (1) Criteria add(Criterion criterion)

  用于添加查询条件,相当于设置HQL中的where从句。当有多个查询条件时,可以逐个增加。例如:

  Criteria crit = session.createCriteria(Product.class);

          crit.add(Restrictions.gt("price",new Double(25.0)));

          crit.add(Restrictions.gt("name","Clothes"));

  List results = crit.list();

或者使用方法链编程风格:

  List results=session.createCriteria(Product.class)

   .add(Restrictions.gt("price",new Double(25.0)))

   .add(Restrictions.gt("name","Clothes"))

   .list();

  多个add相当于对查询条件进行and操作,即要求同时满足这些条件

  (2) Criteria addOrder(Order order)

  如果需要排序,可以使用CriteriaaddOrder()方法增加排序用的Order类。

  (3) Criteria createAlias(String associationPath, String alias) 

     Criteria createAlias(String associationPath, String alias, int joinType) 

List cats = sess.createCriteria(Cat.class)    .createAlias("kittens", "kt")    .createAlias("mate", "mt")    .add( Restrictions.eqProperty("kt.name", "mt.name") )    .list();

  用于设置连接查询,第一种重载形式使用的是默认的内连接;第二种重载形式可以选择连接方式。

  associationPath:属性的路径,使用点“.”作为分割符。例如,Basiccar持久化类中有集合属性persons,而persons中的元素是持久化类Person,而Person类中有集合属性clotheses,其中存有关联对象clothes,如果要从Basiccar对象关联到clothes对象,属性路径就写成:persons.clotheses,使用点隔开。

  alias:关联属性的别名,后面可以使用这个别名来设置关联条件。

  joinType:连接查询时选择的关联方式。joinType可以是内连接CriteriaSpecification.INNER_JOIN(默认值)、全连接CriteriaSpecification.FULL_JOIN, 或者左连接CriteriaSpecification.LEFT_JOIN

  (4) Criteria createCriteria(String associationPath) 

     Criteria createCriteria(String associationPath, int joinType)  

  Criteria createCriteria(String associationPath, String alias)  

  Criteria createCriteria(String associationPath, String alias, int joinType)  

  创建一个指向主类关联的实体的criteria查询,在进行存在关联关系的对象检索时会用到。

  joinType可以指定关联是内连接、左联接还是全连接。alias则可以指定别名。

  返回值是被创建的子查询。

  (5) Criteria setProjection(Projection projection)

  如果需要使用投影查询、聚集函数等,可以按需要生成Projection类,然后使用CriteriasetProjection()方法,对返回结果进行某些列的投影或聚集运算。

  2. DetachedCriteria

  使用Criteria查询需要当前有可用的session,但是,有时构造查询语句时,并不一定能得到可用的session。例如,在分层的项目开发过程中,通常会在表现层,根据用户选择的条件,动态生成SQL语句,进行查询。这个时候,表现层是得不到session的,但是它需要把构造好的查询传给业务层进行session查询。DetachedCriteria就可以解决这个问题,即在表现层,应用程序使用DetachedCriteria来构造查询条件,然后把这个detachedCriteria传递给业务层对象,让业务层在session范围内构造criteria查询。所以,detachedCriteria在构造查询时,session还不可用,detachedCriteria查询面对的是游离的POJO类,而Criteria查询时面对的持久化对象,所以称为detachedCriteria。以下是一个使用DetachedCriteria查询的简单例子。

  DetachedCriteria detachedCriteria= DetachedCriteria.forClass (BasicCar.class); detachedCriteria.add(Restrictions.eq("id", new Integer(1)));

  上面的代码片段先创建了一个DetachedCriteria的实例,然后只要在有可用的session时,使用它的getExecutableCriteria()方法,把这个可用的session关联进来即可,它会返回一个在这个session内进行查询的criteria类。代码如下所示:

  Criteria crit=detachedCriteria.getExecutableCriteria(session);

   List results = crit.list();

  DetachedCriteria 提供了4个静态方法forClass(Class)forEntityName(Name)进行DetachedCriteria实例的创建。DetachedCriteria也提供了add(Criterion)addOrder(Order)setProjection(Projection)createAlias()createCriteria()等方法用于构造查询及其返回结果,与Criteria提供的函数不同的是,DetachedCriteria类提供的函数返回也是DetachedCriteria 类。

  3. CriterionRetrictions

  CriterionCriteria接口的add()方法调用,作为查询条件。内置的Criterion类型由Restrictions这个工厂类提供。实现Criterion接口的可以用来作为查询条件的类包括ExpressionExampleJunction等。

  Criterion的类图关系如图8-2所示。

 

图8-2  Criterion相关类图

  4. ProjectionProjections

  Projection接口是Criteria查询结果集的投影表示。内置的Projection类由Projections工厂类提供。实现projection接口的类包括AliasedProjectionDistinctProjectionListSimpleProjectionSQLProjection5个。Projection的类图如图8-3所示。

 

图8-3  Projection相关类图

  Projection接口被作为CriteriasetProjection()函数的参数,对查询结果进行选择某些属性的投影,进行avgmaxmincountsum等聚集运算。

  Projections提供多种静态方法来产生对查询的结果进行各种运算的projection实例。

  表8-1列出了Projections提供的各种结果运算的函数,以及相应的HQL运算符。

表8-1  Projections的函数

意    思

Projections函数(重点)

HQL例子

1、计算平均值

avg(String?propertyName)

Select avg(o.property) from Object o

2、计算数目

count(String?propertyName)

Select count(o.property) from Object o

3、过滤相同值的属性然后计算数目

countDistinct(String?propertyName)

Select count(distinct o.property) from Object o

4、过滤相同值的属性

distinct(Projection?proj)

Select distinct o.property from Object o

5、按某个属性分组

groupProperty(String?propertyName)

Criteria crit = session.createCriteria(BasicCar.class)

.setProjection(Projections.groupProperty("name"));

 

From Object o group by o.property

6、取对象的主键

id()

Select o.id from Object o

7、计算最大值

max(String?propertyName)

Select max(o.property) from Object o

8、计算最小值

min(String?propertyName)

Select min(o.property) from Object o

9、投影某个属性

property(String?propertyName)

Select o.property from Object o

10、计算行数目

rowCount()

Select count(*) from Object o

11、计算总和

sum(String?propertyName)

Select sum(o.property) from Object o

5. Order(重点)

  Order类提供对Criteria查询结果集的排序,其静态函数生成升序或降序的Order类,被作为Criteria的参数传给addOrder()方法。

  其主要函数有:

  static Order asc(String propertyName) 按降序排

static Order desc(String propertyName) 按升序排

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

 

8.1.2  使用Expression类和Example类设置查询条件

  下面分别介绍Expression类和Example类的查询条件。

  1Expression类(了解)

Expression类由Restrictions工厂类的各个设置条件的静态方法产生。例如,Restrictions类中的gt(String propertyName, Object value)静态方法,用于设置某个属性等于某个值的查询条件,返回的SimpleExpression相当于where propertyName='value'的条件。

方法

描述

Expression.eq

对应SQL“field=value”表达式

如:Expression.eq(“name”,”zx”);

Expression.allEq

方法的参数为一个Map类型对象,包含多个名/值对对应关系,相当于多个Expression.eq的叠加

Expression.gt

对应SQL“field>value”表达式

Expression.ge

对应SQL“field>=value”表达式

Expression.lt

对应SQL“field”表达式

Expression.le

对应SQL“field<=value”表达式

Expression.between

对应SQL语句的between表达式,如:查询年龄在2127岁之间的用户,可以写成Expression.between(“age”,new Integer(21),new Integer(27));

Expression.like

对应SQL语句的”field like value”表达式

Expression.in

对应SQL语句的“field in(……)”表达式

Expression.eqProperty

用于比较两个属性值,对应”field=field”SQL表达式

Expression.gtProperty

用于比较两个属性值,对应”field>field”SQL表达式

Expression.geProperty

用于比较两个属性值,对应”field>=field”SQL表达式

Expression.ltProperty

用于比较两个属性值,对应”field表达式

Expression.leProperty

用于比较两个属性值,对应”field<=field”SQL表达式

Expression.and

对应SQL语句的And关系组合,如:Expression.and(Expression.eq(“name”,”zx”),Expression.eq(“sex”,”1”));

Expression.or

对应SQL语句的Or关系组合,如:Expression.or(Expression.eq(“name”,”zx”),Expression.eq(“name”,”zhaoxin”));

Expression.sql

作为补充这个方法提供了原生SQL语句查询的支持,在执行时直接通过原生SQL语句进行限定,如:Expression.sql(“lower({alias}.name) like (?)”,“zhao%”,Hibernate.STRING) ;在运行时{ alias }将会由当前查询所关联的实体类名替换,()中的?将会由”zhao%”替换,并且类型由Hibernate.STRING指定。

 

  表8-2列出了Restrictions提供的各种条件设置,以及相应的HQL运算符。

表8-2  Restrictions的函数

意    思

Restrictions函数(重点)

HQL例子

1、查询条件逻辑and运算

and(Criterion?lhs, Criterion?rhs)

From Object o where o.property1 = ? and o.property2=?

2、检索在两个数值之间的

between(String?propertyName, Object?lo,

 Object?hi)

From Object o where o.property between ? and ?

3、等于

eq(String?propertyName, Object?value)

eqProperty(String?propertyName, String?otherPropertyName)

Eg:   List cats = sess.createCriteria(Cat.class)       .createAlias("kittens", "kt")       .createAlias("mate", "mt")       .add( Restrictions.eqProperty("kt.name", "mt.name") )       .list();

From Object o where 

o.property=?

4、大于等于

ge(String?propertyName, Object?value)

geProperty(String?propertyName, String?otherPropertyName)

From Object o where 

o.property>=?

5、大于

gt(String?propertyName, Object?value)

gtProperty(String?propertyName, String?otherPropertyName)

From Object o where 

o.property>?

6、主键等于

idEq(Object?value)

Criteria crit = session.createCriteria(BasicCar.class)

.add( Expression.idEq(new Long(1)) );

 

From Object o where o.id=?

7、字符串匹配,不区分大小写

islike(String?propertyName, Object?value)

islike(String?propertyName, String?value, MatchMode?matchMode)

 

Criteria crit = session.createCriteria(BasicCar.class)

.add(Restrictions.islike("name","a", MatchMode.END));

 

List cats = sess.createCriteria(Cat.class)    .add( Restrictions.like("name", "Fritz%") )

 

From Object o where lower 

(o.property) like ??

(续表)   

意    思

Restrictions函数

HQL例子

8、范围运算

in(String?propertyName, Collection?values)

in(String?propertyName, Object[]?values)

From Object o where o.property in(‘a’,’b’…)

  .add( Restrictions.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )

9、检查对象的一个集合属性是否为空,也就是在多对多或多对一双向关联中,“方对应的方为空,没有关联的

isEmpty(String?propertyName)

From Object o where 

o.properties is empty

10、检查对象的一个集合属性是否不为空

isNotEmpty(String?propertyName)

From Object o where 

o.properties is not empty

11、一个属性是否不为空

isNotNull(String?propertyName)

From Object o where o.property is not null

12、一个属性是否为空

isNull(String?propertyName)

 

Criteria crit = session.createCriteria(BasicCar.class)

.add(Restrictions.isNull("name"));

 

From Object o where o.property 

is null

13、小于等于

le(String?propertyName, Object?value)

leProperty(String?propertyName, String?otherPropertyName)

From Object o where 

o.property<=?

14、字符串匹配

like(String?propertyName, Object?value)

like(String?propertyName, String?value, MatchMode?matchMode)

Criteria crit = session.createCriteria(BasicCar.class)

.add(Restrictions.like("name","A%"));

 

From Object o where o.property 

like ‘??’

15、小于

lt(String?propertyName, Object?value)

ltProperty(String?propertyName, String?otherPropertyName)

From Object o where 

o.property

猜你喜欢

转载自blog.csdn.net/zxssoft/article/details/83054980