Session接口
Session接口里面本身所定义的数据查询只有一个根据ID查询的操作方法,但是这个方法有两个定义
根据主键查询:
load(Class<T> theClass, Serializable id) |
根据主键查询:
get(String entityName, Serializable id)
get查询不存在的ID会返回null,而load会报错
面试题:请问Hibernate中定义的Session中get()与load()方法有什么区别?
get()和load()方法都是在Session接口中定义的根据主键查询的操作;
get()方法查询不存在会返回null,
load()方法查询时,如果主键不存在,则抛出异常.
Query查询
面对数据操作中,数据查询的部分永远都是最为复杂的部分,所以来讲如果要进行更加合理的,那么必须依靠Query接口来实现,而如果要想取得此接口的实例化对象,必须依靠Session接口完成,在Session接口中定义有如下的方法:取得Query接口对象
Query createQuery(String queryString)此处表示传入一个hql语法进行数据查询(Hibernat Query Language);
在Query接口里面主要定义如下几个操作方法:
●设置要操作的数据:public Query setXxx(int position,数据类型 val)
●设置参数:public Query setParameter(int position,Object val);
●取得单个查询结果:public Object uniqueResult();
●查询全部数据 public List list()
●数据更新:public int executeUpdate()
数据查询
在Hibernate里面Session的查询不能够胜任于复杂查询,所以现在的所有查询都通过Query接口完成,在这个接口里面要使用hql语言(及其类似 于SQL语句)
范例:查询全部数据
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class QueryDemoA {
public static void main(String[] args) {
String hql="FROM News AS n";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
List<News> all=query.list();
Iterator<News> iterator =all.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
HibernateSessionFactory.closeSession();
}
}
现在通过以上代码可以发现如下几点:
●在Hiberante里面使用的都是HQL,但是在使用HQL的时候一定要注意,FROM子句后面跟的是POJO类的名字,必须注意大小写"News.java"(News),而"AS"指的就是别名,一般情况下可以省略
●在使用Hiberante进行数据查询的时候,发现所有的内容都会以POJO类的形式返回,所有的实例化操作部分都由Hibernate自动帮助用户处理了,
所谓的HQL语法的结构非常类似于SQL语句,那么也可以编写SELECT语句,但是大部分人不会这么写.
范例:查询指定数据列
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class QueryDemoB {
public static void main(String[] args) {
String hql="SELECT n.title,n.item FROM News AS n";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
List<Object[]> all=query.list();
Iterator<Object[]> iterator =all.iterator();
while(iterator.hasNext()){
Object[] obj=iterator.next();
System.out.println(obj[0]+","+obj[1]);
}
HibernateSessionFactory.closeSession();
}
}
此时的代码的确是进行了数据列的操作限制,但是其结果发现为了保证查询,那么返回的数据不再自动转换为POJO类,而是以对象数组的形式返回,相比较POJO类型,以上的操作明显不方便.
范例:使用限定查询
package cn.zwb.test;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
public class QueryDemoD {
public static void main(String[] args) {
String hql="FROM News n WHERE n.nid=?";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setParameter(0, 3); //?从0开始,所有的类型都由Hibernate自己处理,
System.out.println(query.uniqueResult());
}
}
模糊查询在Query中可以继续像SQL那样直接使用
范例:实现模糊查询
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class QueryDemoE {
public static void main(String[] args) {
String hql="FROM News n WHERE n.title LIKE ?";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setParameter(0, "%啦啦%"); //?从0开始,所有的类型都由Hibernate自己处理,
List<News> all=query.list();
Iterator<News> iterator =all.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
HibernateSessionFactory.closeSession();
}
}
各个数据库之中最麻烦的在于分页的支持不同,而Hibernate是一个跨数据库的工具,所以里面的分页将使用统一的方式进行处理,在Query接口里面定义有两个操作方法;
●设置开始行:public Query setFirstResult(int firstResult);
●设置最大返回行:public Query setMaxResults(int maxResults)
使用分页查询
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class QueryDemoF {
public static void main(String[] args) {
String hql="FROM News n ";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setFirstResult((6-1)*2);
query.setMaxResults(2);
List<News> all=query.list();
Iterator<News> iterator =all.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
HibernateSessionFactory.closeSession();
}
}
不管是什么数据库,只要是设置了分页都会由Hibernate自己进行适应
Query接口进行数据统计
package cn.zwb.test;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
public class QueryDemoG {
public static void main(String[] args) {
String hql="SELECT COUNT(*) FROM News n ";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
System.out.println(((Long)query.uniqueResult()).intValue());
HibernateSessionFactory.closeSession();
}
}
Hibernate中返回的数据个数统计的类型为Long,如果要使用int则还需要将Long变为int
使用SQL查询(不建议使用)
即使HQL的语法很像SQL语法,但是它依然不是SQL,所以很对时候可能支持度有限.所以为了解决这样的问题,在Hibernate里面也可以使用普通的SQL语句进行数据的查询,但是如果要想将查询结果变为POJO类的形式,则需使用转换操作
如果要创建SQL查询,在Session接口里面定义有如下方法:
●创建SQL查询:public SQLQuery createSQLQuery(String queryString);
查询占位符
在之前编写的时候使用的HQL的占位符都是"?"(推荐做法),但是在HQL里面对于占位符还有另外一种形式":名称描述",这样的目的主要是为了解决设置的内容过多的时候,"?"容易数不清楚
范例:使用其他占位符
package cn.zwb.test;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
public class QueryDemoG {
public static void main(String[] args) {
String hql="FROM News as n WHERE n.nid=:pnid";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setParameter("pnid", 5);
System.out.println(query.uniqueResult());
HibernateSessionFactory.closeSession();
}
}
但是:和?不可以一起使用,如果要想混合使用要将?放在前面,
更新操作
在Hibernate最早设计的时候,所有的更新操作只能够通过update()方法或者是delete()执行,按时随着时间的发展,发现一个问题,如果使用这些方法无法实现部分数据的更新.
从Hibernate 2.x开始针对于Query接口实现了功能的扩充,让其可以实现数据更新操作.
范例:使用Query接口更新数据
package cn.zwb.test;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
public class QueryUpdateA {
public static void main(String[] args) {
String hql="UPDATE News SET title=?,visits=?";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setParameter(0, "修改标题l");
query.setParameter(1, 50);
int len=query.executeUpdate();
System.out.println("更新行数"+len);
HibernateSessionFactory.getSession().beginTransaction().commit();
HibernateSessionFactory.closeSession();
}
}
范例:实现数据删除操作:
package cn.zwb.test;
import org.hibernate.Query;
import cn.zwb.dbc.HibernateSessionFactory;
public class QueryUpdateB {
public static void main(String[] args) {
String hql="DELETE News WHERE nid=?";
Query query=HibernateSessionFactory.getSession().createQuery(hql);
query.setParameter(0, 4);
int len=query.executeUpdate();
System.out.println("更新行数"+len);
HibernateSessionFactory.getSession().beginTransaction().commit();
HibernateSessionFactory.closeSession();
}
}
Criteria接口
大部分情况下如果要使用查询操作,首先一定是HQL查询,但是在Hibernate之中有一个特殊情况,Hibernate属于ORMapping的映射框架,那么如果是ORMapping的映射框架,所有的操作偶应该以对象为主进行使用,那么Query的使用就不符合于这种要求了,所以在查询的基础上又扩充了一个基于对象模式的查询接口:Criteria,而这个接口的创建依靠session接口Criteria createCriteria(Class persistentClass)
范例:查询全部数据
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class CriteriaDemoA {
public static void main(String[] args) {
Criteria criteria=HibernateSessionFactory.getSession().createCriteria(News.class);
List<News> allList=criteria.list();
Iterator<News> iter =allList.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
HibernateSessionFactory.closeSession();
}
}
如果只是这种简单的查询,那么使用Criteria接口一定要比使用Query接口更加容易
但是实际的开发之中,虽然需要查询全部,但是很多时候都需要限定查询,所以在Criteria里面也支持查询条件,此接口定义了如下一个增加查询条件的方法
Criteria add(Criterion criterion)
那么对于所有的条件的创建还需要使用另外一个类:
- org.hibernate.criterion.Restrictions
这个类定义了如下几个操作方法:
●逻辑运算:
丨-与运算(AND)
public static Conjunction and(Criterion... predicates)
丨-或运算(OR)
public static Disjunction or(Criterion... predicates)
丨-非运算
public static Criterion not(Criterion expression)
●关系运算:
|-"=="
public static SimpleExpression eq(String propertyName, Object value)
|-"!="
public static SimpleExpression ne(String propertyName, Object value)
|-">"
public static SimpleExpression gt(String propertyName, Object value)
|-">="
public static SimpleExpression ge(String propertyName, Object value)
|-"<"
public static SimpleExpression lt(String propertyName, Object value)
|-"<="
public static SimpleExpression le(String propertyName, Object value)
|-"LIKE"
public static SimpleExpression like(String propertyName, Object value)
|-"IN"
public static Criterion in(String propertyName, Collection values)
|-"BETWEEN...AND"
public static Criterion between(String propertyName, Object low, Object high)
|-"IS NULL"
public static Criterion isNull(String propertyName)
|-"IS NOTNULL"
public static Criterion isNotNull(String propertyName)
范例:根据ID查询
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class CriteriaDemoA {
public static void main(String[] args) {
Criteria criteria=HibernateSessionFactory.getSession().createCriteria(News.class);
criteria.add(Restrictions.eq("nid", 3));
List<News> allList=criteria.list();
Iterator<News> iter =allList.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
HibernateSessionFactory.closeSession();
}
}
范例:取得访问量大于100的信息
package cn.zwb.test;
import java.util.Iterator;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class CriteriaDemoC {
public static void main(String[] args) {
Criteria criteria=HibernateSessionFactory.getSession().createCriteria(News.class);
criteria.add(Restrictions.gt("visits",100));
List<News> allList=criteria.list();
Iterator<News> iter =allList.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
HibernateSessionFactory.closeSession();
}
}
在整个Criteria操作之中,如果要说最有用处的操作,只有一个:IN()操作,因为这个接口的IN操作可以直接将要查询的数据以Collection形式保存.
范例:使用IN查询
package cn.zwb.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class CriteriaDemoD {
public static void main(String[] args) {
Set<Integer> ids=new HashSet<Integer>();
ids.add(1);
ids.add(3);
Criteria criteria=HibernateSessionFactory.getSession().createCriteria(News.class);
criteria.add(Restrictions.in("nid",ids));
List<News> allList=criteria.list();
Iterator<News> iter =allList.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
HibernateSessionFactory.closeSession();
}
}
在Criteria接口操作的时候还可以设置排序,里面提供了排序的方式:
Criteria addOrder(Order order)
●升序排列:
public static Order asc(String propertyName)
●降序排列:
public static Order desc(String propertyName)
package cn.zwb.test;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import cn.zwb.dbc.HibernateSessionFactory;
import cn.zwb.pojo.News;
public class CriteriaDemoD {
public static void main(String[] args) {
Set<Integer> ids=new HashSet<Integer>();
ids.add(1);
ids.add(3);
Criteria criteria=HibernateSessionFactory.getSession().createCriteria(News.class);
criteria.addOrder(Order.desc("nid"));
List<News> allList=criteria.list();
Iterator<News> iter =allList.iterator();
while(iter.hasNext()){
System.out.println(iter.next());
}
HibernateSessionFactory.closeSession();
}
}