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 --> 判断属性是否为空,为空则返回true
Restrictions.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));
List<PojoOrder> orders = 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<Object[]> list = sqlQuery.list();
for (Object[] object : list) {
System.out.println(Arrays.toString(object));
}
transaction.commit();
session.close();
}
错误:
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
List<PojoOrder> list = 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();
List<PojoOrder> orders =
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方法:
<hibernate-mapping package="cn.cvu.hibernate.domain">
<class name="PojoOrder">
<!-- 略 -->
</class>
<query name="findPojoOrdersByPojoUserName">
<![CDATA[ from PojoOrder where user.name = ? ]]>
</query>
</hibernate-mapping>
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 ;
select * from 表 1, 表 2 where 表 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<Object>;查询多列,返回List<Object[]>
Query query = session.createQuery("select u.id, u.name from PojoUser as u");
List<PojoUser[]> list = query.list();
for (int i = 0; i < list.size(); i++) {
Object[] users = list.get(i); //须用Object封装而不是PojoUser
for (int j = 0; j < users.length; j++) {
System.out.println(users[j]);
}
}
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();
//在数据层执行查询
List<PojoOrder> list = criteria.getExecutableCriteria(session).list();
for (PojoOrder order : list) {
System.out.println(order);
}
transaction.commit();
session.close();
}
- end