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