读书人

Hibernate 运用 criteria

发布时间: 2012-10-07 17:28:51 作者: rapoo

Hibernate 使用 criteria
要料管理系行操作,最基本的就是使用SQL(Standard Query Language)句,大部份的料都支援的SQL句,然而也有一些特定於料的SQL句,用程式配合SQL句行料查,若使用到特定於料的SQL句,程式本身有相依於特定料的。

使用Hibernate,即使您不了解SQL的使用撰,也可以使用它所提供的API行SQL句查,org.hibernate.CriteriaSQL行封,您可以Java物件的合各查件,由Hibernate自您生SQL句,而不用特管理SQL料相依的。

以最基本的查,如果您想要查某物件所的料表中所有的容,您可以如下行查:

Criteria criteria = session.createCriteria(User.class);
List users = criteria.list();

for(Iterator it = users.iterator(); it.hasNext(); ) {
User user = (User) it.next();
System.out.println(user.getId() +
" \t " + user.getName() +
"/" + user.getAge());
}


Criteria建立後,若不予任何的件,是查物件所表格之所有料,如果您行以上的程式片段,於定中定了了Hibernate的”show_sql”性,可以在主控下看到以下的SQL句之生:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_

Criteria基本查件定

org.hibernate.Criteria上是件附加的容器,如果想要定查件,要使用org.hibernate.criterion.Restrictions的各方法回org.hibernate.criterion.Criteria例,回的每org.hibernate.criterion.Criteria例代表著一件,您要使用org.hibernate.Criteria的add()方法加入些件例,例如查”age”大於20且小於40的料:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.gt("age", new Integer(20)));
criteria.add(Restrictions.lt("age", new Integer(40)));
List users = criteria.list();

for(Iterator it = users.iterator(); it.hasNext(); ) {
User user = (User) it.next();
System.out.println(user.getId() +
" \t " + user.getName() +
"/" + user.getAge());
}

Restrictions的gt()方法表示大於(great than)的件,而lt表示小於(less than)的件,行以上程式片段,察所生的SQL句,使用whereand子句完成SQL的件查:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age>? and this_.age

使用add()方法加入件,是使用and合件,如果要用or的方式合件,可以使用Restrictions.or()方法,例如合age等於(eq)20或(or)age空(isNull)的件:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.or(
Restrictions.eq("age", new Integer(20)),
Restrictions.isNull("age")
));
List users = criteria.list();

察所生的SQL句,使用whereor子句完成SQL的件查:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=? or this_.age is null)

您也可以使用Restrictions.like()方法行SQL中like子句的功能,例如查”name”中名”just”的料:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.like("name", "just%"));
List users = criteria.list();

察所生的SQL句如下:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name like ?

Restrictions的常用限定查方法如下表所示:

方法 明
Restrictions.eq 等於
Restrictions.allEq 使用Map,使用key/value行多等於的比
Restrictions.gt 大於 >
Restrictions.ge 大於等於 >=
Restrictions.lt 小於 <
Restrictions.le 小於等於 <=
Restrictions.between SQL的BETWEEN子句
Restrictions.like SQL的LIKE子句
Restrictions.in SQL的in子句
Restrictions.and and
Restrictions.or or

Criteria查件定

使用Criteria行查,不能合出SQL中where子句的功能,可以合出如排序、、分等的查功能。

排序

您可以使用Criteria行查,使用org.hibernate.criterion.Order果行排序,例如使用Oder.asc(),指定根”age”由小到大排序(反之使用desc()):

Criteria criteria = session.createCriteria(User.class);
criteria.addOrder(Order.asc("age"));
List users = criteria.list();

注意在加入Order件,使用的是addOrder()方法,而不是add()方法,在生SQL句,使用order byasc(desc)行排序指定:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ order by this_.age asc

限定查

Criteria的setMaxResults()方法可以限定查回的,如果配合setFirstResult()定回查果第一料的位置,就可以的分,例如回第51之後的50料(如果有的):

Criteria criteria = session.createCriteria(User.class);
criteria.setFirstResult(51);
criteria.setMaxResults(50);
List users = criteria.list();

根您所指定得料,Hibernate自生料相依的限定查子句,例如在MySQL中,使用limit生以下的SQL句:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ?



您可以查果行作,使用org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min()、 countDistinct()等方法,再搭配Criteria的setProjection()方法加入件定,例如查果的"age"作平均:

Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.avg("age"));
List users = criteria.list();

上面的程式由Hibernate自生SQL的avg函行平均算:

Hibernate: select avg(this_.age) as y0_ from T_USER this_



可以配合Projections的groupProperty()果行分,例如以"age"行分,也就是如果料中"age"如果有 20、20、25、30,以下示20、25、30:

Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(Projections.groupProperty("age"));
List users = criteria.list();

上面的程式由Hibernate自生SQL的group by子句行分算:

Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age

如果想同合分功能,可以使用org.hibernate.criterion.ProjectionList,例如下面的程式算每年各有多少人:

ProjectionList projectionList = Projections.projectionList();
projectionList.add(Projections.groupProperty("age"));
projectionList.add(Projections.rowCount());

Criteria criteria = session.createCriteria(User.class);
criteria.setProjection(projectionList);
List users = criteria.list();

察所生的SQL句,使用group by先行分,再每分行count函的

Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age

根已知物件行查

定查件非一定要使用Restrictions,如果性件很多,使用Restrictions也不方便,如果有一已知的物件,可以根物件作查的依,看看是否有性之似的物件,例如:

User user = new User();
user.setAge(new Integer(30));

Criteria criteria = session.createCriteria(User.class);
criteria.add(Example.create(user));

List users = criteria.list();

您可以透org.hibernate.criterion.Example的create()方法建立Example例,Example作了Criteria介面,因此可以使用add()方法加入至Criteria件定之中,Hibernate自掉空性,根已知物件上已定的性,判定是否生於where子句之中:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?)

定SQL本

如果您了解如何撰SQL句,想要定一些Hibernate生SQL的本,您也可以使用Restrictions的sqlRestriction()方法,提供SQL法本作限定查,例如查name以cater的料:

Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));
List users = criteria.list();

其中alias被替User相的名,而?被替cater%,也就是第二所提供的值,sqlRestriction()方法第一所定的是where子句的部份,所以在SQL撰,不必再where,察所生的SQL句,使用您所定的SQL本作基,完成SQL的件查:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name LIKE (?)

如果有多查件,例如between子句的查,可以如下:

Criteria criteria = session.createCriteria(User.class);
Integer[] ages = {new Integer(20), new Integer(40)};
Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};
criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));
List users = criteria.list();

察所生的SQL句如下:

Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age BETWEEN (?) AND (?)

使用DetchedCriteria

CriteriaSession定,其生命期跟著Session束而束,使用Criteria行查,每次都要於行期建立物件,加入各查件,著Session的回收,Criteria也跟著回收。

了能重使用Criteria物件,在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteria,您可以先建立DetchedCriteria例,加入各查件,於需要查再Session定,得一定Session的Criteria物件,例如:

// 先建立DetchedCriteria物件
DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class);
// 加入查件
detchedCriteria.add(Restrictions.ge("age",new Integer(25)));

Session session = sessionFactory.openSession();
// 定Session返回一Criteria例
Criteria criteria = detchedCriteria.getExecutableCriteria(session);

List users = criteria.list();



Hibernate的Criteria API可以您使用物件的方式,合出查料系的件,Hibernate自依您所使用的料,生SQL句,您的用程式在存取料,不致於因撰了特定的SQL而相依於特定的料,如果您的人不熟悉SQL句的撰,也可以著使用Criteria解查料的需求。

读书人网 >软件架构设计

热点推荐