1.导航对象图:
已经获得持久态对象,通过对象引用关系,执行关联对象的查询
1)Query查询的链式写法:
public void testQuery(){ Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); /**原多行写法*//* Query query = session.createQuery("from PojoUser where t_name= :xxx"); query.setParameter("xxx", "PapaRoach"); List list = query.list(); */ /**链式写法*/ List list = session.createQuery("from PojoUser where t_name= :xxx").setParameter("xxx", "PapaRoach").list(); System.out.println(list); transaction.commit(); session.close(); }
2)绑定参数:
(1)绑定基本类型参数:
(2)绑定实体参数:
/**使用ID*//* Query query = session.createQuery("from PojoOrder where user= ?"); query.setEntity(0, new PojoUser(1)); //构造方法传入ID创建托管对象 List list = query.list(); */ /**使用实体的属性Name*/ Query query = session.createQuery("from PojoOrder where user.name= ?"); query.setParameter(0, "PapaRoach"); List list = query.list();
2.OID检索方式:
根据OID检索get / load
3.HQL检索方式:
根据HQL语句进行检索。session.createQuery(hql)
4.QBC检索方式:
QBC(Query By Criteria) 根据Criteria对象完成检索。session.createCriteria(domain.class)
1)标准查询:
public void testQuery(){ Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); /** 1.查询全部 **//* Criteria criteria = session.createCriteria(PojoUser.class); List users = criteria.list();*/ /** 2.查询指定ID **//* Criteria criteria = session.createCriteria(PojoOrder.class); criteria.add(Restrictions.eq("user", new PojoUser(1))); //必须ID */ /** 3.通过别名查询指定属性 **/ Criteria criteria = session.createCriteria(PojoOrder.class); criteria.createAlias("user", "u"); //创建别名 criteria.add(Restrictions.eq("u.name", "PapaRoach")); //必须别名.属性 List orders = criteria.list(); System.out.println(orders); transaction.commit(); session.close(); }
2)QBC常用限定方法:
Restrictions.eq --> equal,等于
Restrictions.allEq --> 参数为Map对象,使用key/value进行多个等于的比对,相当于多个Restrictions.eq的效果Restrictions.gt --> great-than > 大于Restrictions.ge --> great-equal >= 大于等于Restrictions.lt --> less-than, < 小于Restrictions.le --> less-equal <= 小于等于Restrictions.between --> 对应SQL的between子句Restrictions.like --> 对应SQL的LIKE子句Restrictions.in --> 对应SQL的in子句Restrictions.and --> and 关系Restrictions.or --> or 关系Restrictions.isNull --> 判断属性是否为空,为空则返回trueRestrictions.isNotNull --> 与isNull相反Restrictions.sqlRestriction --> SQL限定的查询Order.asc --> 根据传入的字段进行升序排序Order.desc --> 根据传入的字段进行降序排序MatchMode.EXACT --> 字符串精确匹配。相当于"like 'value'"MatchMode.ANYWHERE --> 字符串在中间匹配。相当于"like '%value%'"MatchMode.START --> 字符串在最前面的位置。相当于"like 'value%'"MatchMode.END --> 字符串在最后面的位置。相当于"like '%value'"3)复杂查询:
早期hibernate版本进行条件查询时使用Expression,目前Expression已经过时,推荐使用父类Restrictions
Criteria criteria = session.createCriteria(PojoOrder.class); // 条件一:lt=id小于5。取值0-4 SimpleExpression expression1 = Restrictions.lt("id", 5); // 条件二:like=name包含'ne'。ilike忽略大小写;like不忽略 SimpleExpression expression2 = Restrictions.like("name", "%球%"); // 并列传入两个条件 criteria.add(Restrictions.and(expression1, expression2)); Listorders = criteria.list(); System.out.println(orders);
5.本地SQL检索方式:
根据SQL语句完成检索。session.createSQLQuery(sql);主要用于企业对查询进行优化时
1)SQLQuery查询代码:
@Test public void testSQLQuery(){ Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); String sql="select * from tb_user, tb_order where tb_order.t_user_id=tb_user.t_id and tb_user.t_name=?"; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.setParameter(0, "Eminem"); List
错误:
org.hibernate.loader.custom.NonUniqueDiscoveredSqlAliasException: Encountered a duplicated sql alias [t_id] during auto-discovery of a native-sql query
解决:
问题出在 Query须要使用别名来区分相同名称的列。
String sql= "SELECT u.t_id AS uid, u.t_address AS uadd, o.t_id AS oid, o.t_name AS oname "+ "FROM tb_user AS u, tb_order AS o "+ "WHERE o.t_user_id = u.t_id "+ "AND u.t_name=?";
2)使用Bean封装返回数据:
public void testSQLQuery(){ Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); /* 别名不能和POJO中的变量名相同 * 必须查询*,或指定全部字段 */ String sql = "SELECT * "+ "FROM tb_user as userr, tb_order as ord "+ "WHERE ord.t_user_id = userr.t_id "+ "AND userr.t_name=? "; SQLQuery sqlQuery = session.createSQLQuery(sql); sqlQuery.setParameter(0, "Eminem"); sqlQuery.addEntity(PojoOrder.class); //查询结果封装到一个PojoOrder对象,仅用于SqlQuery Listlist = sqlQuery.list(); System.out.println(list); transaction.commit(); session.close(); }
6.多态查询:
查询PO类的父类,可将对应表中全部子类数据查出
public void testQuery(){ Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); //直接查询对象 //Query query = session.createQuery("from PojoOrder"); //多态查询,会将其子类全部查出。非POJO类需用全路径 Query query = session.createQuery("from java.lang.Object"); List list = query.list(); System.out.println(list); transaction.commit(); session.close(); }
7.order_by查询结果排序:
1)HQL方式:
//hql=from Pojo order by 主键属性 顺序 List orders = session.createQuery("from PojoOrder order by id desc").list();
2)QBC方式:
//标准查询器(对象).addOrder(顺序=(hibernate的排序器(排序参照))).list(); Listorders = session.createCriteria(PojoOrder.class) .addOrder(org.hibernate.criterion.Order.desc("id")) .list();
8.setFirstResult分页查询:
Query和Criteria都提供。setFirstResult开始记录索引,setMaxResults查询条数
1)HQL:
Query query = session.createQuery("from PojoOrder"); query.setFirstResult(3); //索引值。从0开始 query.setMaxResults(3); //查询条数 List list = query.list(); System.out.println(list);
2)QBC:
Criteria criteria = session.createCriteria(PojoOrder.class); criteria.setFirstResult(3); criteria.setMaxResults(3); List list = criteria.list(); System.out.println(list);
9.uniqueResult单一结果:
主要用于count、sum、max
//Query query = session.createQuery("select count(*) from PojoOrder"); //count返回long //Query query = session.createQuery("select sum(totalprice) from PojoOrder"); Query query = session.createQuery("select max(totalprice) from PojoOrder"); Object value = query.list(); System.out.println(value);
10.NamedQuery命名查询(自定义HQL方法):
常用的HQL在java源代码不便于维护。可将这些语句写入配置文件并命名,以调用API的方式使用
1)在POJO.hbm.xml中配置Query方法:
2)测试:
//直接调用方法名 Query query = session.getNamedQuery("findPojoOrdersByPojoUserName"); //仍需手动传入参数 query.setParameter(0, "Eminem"); List list = query.list(); System.out.println(list);
11.连接查询
多表关联查询。hibernate提供的Oracle、MySql都支持的七种查询:
1)内连接inner join | join与隐式内连接:
返回两个表都存在的数据:
select * from 表1 inner join 表2 on 表1.id = 表2.id ;2)左外连接left outer join | left join :
用左表匹配右表,无论是否完全匹配,左表数据全部返回,右表没有匹配的数据填充null:
select * from 表1 left outer join 表2 on 表1.id = 表2 .id;3)右外连接right outer join | right join :
用左表匹配右表,无论是否完全匹配,右表数据全部返回,左表没有匹配的数据填充null:
select * from 表1 right outer join 表2 on 表1.id = 表2 .id;4)迫切左外连接left outer join fetch | left join fetch :
迫切左外连接是hibernate中的hql方式,转为sql后仍然是左外链接。
//hibernate为实现数据完整性,用一方顾客匹配多方订单时,按多方返回的数据有重复 //Query query = session.createQuery("from PojoUser as u left outer join fetch u.orders"); //去重 Query query = session.createQuery("select distinct(u) from PojoUser as u left outer join fetch u.orders"); List list = query.list(); System.out.println(list.size());
12.投影查询:
查询数据表中一部分字段:
//指定查询一列,返回List
1)将结果封装到List集合:
select new list(id,name) from POJO ;
2)将结果封装到Map集合:
select new map(id,name) from POJO ;
3)将结果封装到POJO对象:
select new POJO(id,name) from POJO ;
这种封装需要POJO类提供对应构造器,POJO(id,name)构造方法。
4)QBC方式的投影:
13.离线条件查询DetachedCriteria(非常重要):
简单条件查询使用HQL,如果是组合条件,复杂查询则使用Criteria。
问题:在实际开发中业务层没有Session对象,无法session.createCriteria(POJO.class); ,需要使用DetachedCriteria封装查询,然后交给数据层使用以完成查询。
public void testQuery() { //在业务层封装查询 //查询订单 DetachedCriteria criteria = DetachedCriteria.forClass(PojoOrder.class); //须指定别名 criteria.createAlias("user", "u"); //添加条件 criteria.add(Restrictions.eq("u.name", "Eminem")); Session session = UtilGetSession.openSession(); Transaction transaction = session.beginTransaction(); //在数据层执行查询 Listlist = criteria.getExecutableCriteria(session).list(); for (PojoOrder order : list) { System.out.println(order); } transaction.commit(); session.close(); }
- end