1.Criteria
我的理解:Criteria就是Hibernate生成的一个由根据一定约束条件查询session或数据库而得到的结果的List和一些添加约束条件的方法所组成的对象。
(1).创建criteria:Criteria crit = session.createCriteria(MyMessage.class)àList<MyMessage>对象
(2).设置结果集最大个数:crit.setMaxResults(2)
(3).查询、得到结果集:List<MyMessage> messages = crit.list(),list函数执行带有条件的对Criteria对象集合的查询。
注意:如果不使用crit.uniqueResult(),Criteria.list()返回的就是一个List<Object[]>
(4).添加约束:
Criteria.add(Criterion的实现类);
原理:org.hibernate.criterion.Restrictions利用其静态方法创建单个或多个(or、and)约束条件的组合形成SimpleExpression对象,再有Criteria的add方法添加到Criteria对象,最后有list方法执行条件查询返回查询结果。
org.hibernate.criterion.Restrictions静态方法如下:
1) 单个约束:
SimpleExpression extends Criterion;
public static SimpleExpression ne(String propertyName,Object value); //!=
public static SimpleExpression lt(String propertyName,Object value); //<
public static SimpleExpression gt(String propertyName,Object value); //>
public static SimpleExpression le(String propertyName,Object value); //<=
public static SimpleExpression ge(String propertyName,Object value); //>=
public static SimpleExpression like(String propertyName,Object value); //like
//说明:此处的value有4种情况:“%subString”、“subString%”、“%subString%”、“subString”
public static SimpleExpression like(String propertyName,Object subString, MatchMode); //like
//说明:subString表示匹配字符串,MatchMode也有4个常量值:
MatchMode.ANYWHERE //相当于“%subString%”
MatchMode.END; //相当于“subString%”
MatchMode.EXACT; //相当于“subString”
MatchMode.START; //相当于“%subString”
2) 多个约束:
LogicalExpression extends Criterion;
Conjunction extends Criterion;
Disjunction extends Criterion;
Criteria的add方法可以添加多个约束,默认情况下他们之间的关系是and,下面介绍多个约束之间关系不唯一的添加方法:
public static LogicalExpression and(Criterion s1, Criterion s2); //or
public static LogicalExpression or(Criterion s1, Criterion s2); //and
//说明:建立两个单个约束SimpleExpression之间的or、and关系,但是该方法不常用
//常用方式如下:
Conjunction conjunction =Restrictions.conjunction();
conjunction.add(SimpleExpression1);
conjunction.add(SimpleExpression2);
Disjunction disjunction=Restrictions.disjunction();
disjunction.add(conjunction);
disjunction.add(SimpleExpression3);
3) 直接使用sql语句
Retrictions.sqlRestriction(“{alias”.name like ‘%d%’”);
Retrictions.sqlRestriction(“{alias”.name like ?”,”%d%”,new.org.hibernate.type.StringType());
//说明:这样的做法不太常用,其中{alias}就代表表明,不用替换,name是表的某个字段名,第二个方法中根据?指定参数和参数类型,多于一个使用数组代替后两个参数。
(5).分页:
crit.setMaxResults(rows);
crit.setFirstResult((currentPage - 1) * rows);
特别说明:
public String execute() throws Exception {
Session session = HibernateSessionFactory.getSession();
Criteria crit = session.createCriteria(entity);
crit.setMaxResults(rows);
crit.setFirstResult((currentPage - 1) * rows);
List list = crit.list();
for (Object obj : list) {
records.add(obj);
}
session.close();
return SUCCESS;
}
上面这个函数可以作为通用的分页函数:
entity:表示实体全名package.Entity
rows:表示页大小
currentPage:表示当前页码(1,2,3...)
records:是查询得到的记录集,它的getter核setter方法类型既可以是List<List<String>也可以是List<Object>,客户端都可以使用row[field]读取。
field:未知表的字段值,可以建立一个fieldList的getter方法,返回String[] field.splid(“,”)。
详见std_example(pagination)
(6).持久化一个对象:
crit.setMaxResults(1);
crit.add(Restrictions.eq("id", 1));
MyMessage message = (MyMessage) crit.uniqueResult();
必须保证查询结果集只有1条或者为null,否则将会抛出一个org.hibernate.NonUniqueResultException异常
(7).对查询结构进行排序:
crit.addOrder(org.hibernate.criterion.Order.desc("id"));
//desc表示降序,asc表示升序,都是静态方法
(8).多个Criteria之间的关联
Criteria crit1 = session.createCriteria("entity.Order");
Criteria crit2=crit1.createCriteria("customer");
存在关系的两个实体之间可以建立如上关系,单独操作!
(9).聚合和分组(集合映射操作)
Criteria.setProjection(org.hibernate.criterion.AggregateProjection对象);
org.hibernate.criterion.Projections类的静态方法可以创建AggregateProjection对象
例如:
crit.setProjection(Projections.rowCount());
Integer value=(Integer)crit.uniqueResult();
//统计记录总数
Projections.groupProperty("name")//按照name分组
Projections.max("id")//找最大值
Projections.sum("id")//计算总和 等等还有很多,具体使用时再具体统计
org.hibernate.criterion.ProjectionList//可以建立一个映射集合
ProjectionList projList=Projections.projectionList();
projList.add(Projections.groupProperty("name"));
projList.add(Projections.rowCount());
projList.add(Projections.max("id"));
crit.setProjection(projList);
List results=crit.list();
Object array[]=(Object[])results.get(0);
特别注意
1.如果不适用crit.uniqueResult(),Criteria.list()返回的就是一个List< Object[]>
2.约束条件添加的顺序和次数不一样返回的结果也不一样,尤其是对于分组约
(10).QBE (Query By Example)
org.hibernate.criterion.Example implements Criterion;
原理:利用Example的静态方法create来生成一个实现了Criterion的Example对象,供Criteria查询,而前面是通过显式的约束类来生成Criterion对象,这里约束的生成多了一个通过事例提炼约束的过程。
MyMessage message = new MyMessage();
message.setName("gb2312中文");
Example example = Example.create(message);
example.enableLike();//验证没有通过的结论:所用String使用like查询
example.excludeProperty("id");//忽略字段id
example.excludeNone();//忽略默认值为0的字段= example.excludeZeroes();
crit.add(example);
2.Query
我的理解:
a.HQLàSQL
HQL(Hibernate Query Language),HQL就像SQL一样的查询语言,不同的是SQL是针对数据库中的表的而且不区分大小写;而HQL针对的是项目中的实体对象,查询的是实体对象的成员变量,其中变量名应准确描述,关键字和SQL基本一样,也不区分大小写;可以说HQL是面向对象的。
b.QueryàCriterria
Session通过createQuery(hql查询字符串)生成Query对象,Query和Critaria类似,他是Hibernate生成的一个由根据hql语句查询session或者数据库而得到的结果的List所组成的对象。他们的不同之处在于,Query把约束条件变成了HQL语句直接访问session得到查询结果,而Criteria是通过自身提供的方法和接口先构造出约束条件然后再访问session得到查询的结果。
(1).创建query: String hql="from MyMessage";
Query query=session.createQuery(hql); àList<Object> List<Object> results = query.list();
public Query createQuery(String queryString)throws HibernateException;
(2).HQL基本语法:
1)from子句 返回List<Entity>或者List<Entity[]>对象集合
from MyMessage // MyMessage:实体名,经过mapping的实体或其父类
from MyMessage as m //可以简化实体名为m,其中as可以省略,建议不要省略
from entity.MyMessage as m //如果类名有冲突可以使用package.className,当类没有经过mapping映射(如父类)那么必须使用package.calssName
from EntityBean as b1,EntityBean2 as b2 //from后面可以跟多个Bean,用逗号隔开
from java.lang.Object //from后面可以跟Bean的父类,查询结果是所有子类Bean集合
如果想让hibernate生成查询相关实体Bean的SQL语句可以为相关联的实体Bean建立一个父类。
2)select子句 返回List<Object>或者List<Object[]>属性集合
select name ,id from MyMessage
// select后面跟需要返回的实体属性名,多个属性之间用逗号隔开
3)where子句
select name from MyMessage where id>5
select name ,id from MyMessage where id>5 and not(name like '%e%')
//类似于sql的where子句,其中多个条件之间有or和and关系
4)使用命名参数(相当于sql语句中带有的?,sql也支持)
Address address = new Address();
address.setId(2);
sql = "from Employee as e where e.address=:address";
query = session.createQuery(sql);
query.setEntity("address", address);
如上所示,可以为加“:”参数设置指定类型的值,甚至可以使实体类型(此时使用的是实体的主键进行的查询)。
5) order by子句和group by子句(排序和分组)
例句:from MyMessage order by id desc,name asc
select count(*) ,name from MyMessage group by name order by id desc
6) 关联查询
HQL支持如下四种关联:
inner join //内关联
left outer join/left join //左外关联
right outer join/right join //右外关联
注意:当使用select语句时返回List<Object[]>(记录.字段数组),如果存在1:2会生成两条记录;
当仅使用from时返回对象集合List<entity[])(记录=对象),如果存在1:2会出现两条一样的记录;
例如:
7) 聚合函数
avg(...) //求属性平均值
sum(...) //求属性的总和
min(...) //求属性的最小值
max(...) //求属性的最大值
count(...或*或distict...) //求持久化对象数
8) Update,delete和insert语句
例句:update Customer set name='sun' where name='bea'
delete from Customer where name='sun'
insert into MyMessage(id,name) select 50 ,name from MyMessage where id=2
操作流程:
Transaction tx=session.beginTransaction();
String hql="update Customer set name='sun' where name='bea'" ;
Query query=session.createQuery(hql);
int count =query.executeUpdate();
tx.commit();
注意:1.对数据库的更删改操作需要开启一个事物
2.insert语句不支持values操作,因此必须制定插入的位置为select
(3).命名查询(避免hql或者sql语句硬编码到类中,利用配置文件)
这样做的好处
1).可以共享查询语句
2).避免修改类
3).容易整理和测试查询语句
例如:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<query name="myhql">
<![CDATA[select name from MyMessage where id=:id]]>
</query>
<sql-query name="mysql">
<![CDATA[select name from t_message where id=:id]]>
</sql-query>
</hibernate-mapping> //配置文件
Query query =session.getNamedQuery("myhql");
query.setInteger("id", 50);
Session成员:public Query getNamedQuery(String queryName) throws HibernateException;
也支持SQL的原理:当session.getNamedQuery(“mysql”)时根据标签<query> 返回Query对象,<sql-query>返回SQLQuery对象,然而SQLQuery是Query的子类,因此相当于执行了session.createSQLQuery("select name from t_message where id=:id")函数。
(4).使用SQL
原理
Session成员:public SQLQuery createSQLQuery(String queryString) throws HibernateException;该成员生成SQLQuery对象,之后操作与Query基本一样,不同在于query.list()默认返回当前记录的字段值(List<Object[])而不是对象,如果想让其返回对象,需要为sql语句查询的表alias对应实体Entity,工作成员如下:
Public SQLQuery addEntity(Class entityClass);
Public SQLQuery addEntity(String slias, Calss entityCalss);
另外如果使用聚合函数返回数值结果,需要使用以下成员:
Public void addScalar(String filedName,Object Hibernate.TYPE);
事例:
String sql="select * from t_message m";
SQLQuery query=session.createSQLQuery(sql);
query.addEntity("m",MyMessage.class); ...
sql="select count(*) as c from t_message";
query=session.createSQLQuery(sql);
query.addScalar("c",Hibernate.LONG);
Long count=(Long)query.uniqueResult(); ...