(十二)Hibernate的查询方式
一、OID检索方式
按照对象的OID来查询对象。Session的get/load方法提供了这种功能。 如果应用程序中事先知道了OID,就可以使用这种查询对象的方式。
二、导航对象图检索方式
根据已经加载的对象,导航到其他对象. 例如,对于已经加载的Customer对象,可以导航到所有关联的Order对象
三、HQL检索方式
简介:
使用面向对象的HQL查询语言。Hibernate提供了Query接口,它是专门的HQL查询接口,能执行各种复杂的HQL语句。
HQL是面向对象的查询语言,和SQL查询语言有些类似,Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。HQL封装了JDBC的细节
HQL和SQL本质是不一样的:
-HQL查询语言面向对象,Hibernate负责解析HQL语句,然后根据映射文件,把HQL语句翻译成SQL语句。HQL查询语句中主体是类和类的属性。
-SQL查询语言是和关系数据库绑定在一起的,SQL查询语句中主体是数据库表和表的字段。
HQL查询的步骤
-通过session的createQuery(HQL语句)方法创建一个Query对象
-调用Query的list()方法执行查询语句。该方法返回List集合
(1)================= 查找所有对象 ====================
public class Demo {
private Session session;
@Test
public void test() {
//读取配置文件
Configuration conf=new Configuration().configure();
//根据配置创建factory
SessionFactory sessionfactory=conf.buildSessionFactory();
session = sessionfactory.openSession();
Transaction ts=session.beginTransaction();
//HQL语句是面向对象的,from 类名
List<Customer> customerlist=session.createQuery("from Customer").list();
System.out.println(customerlist);
ts.commit();
session.close();
sessionfactory.close();
}
}
(2)================= HQL语句使用别名 ====================
例如:List< Customer > customerlist=session.createQuery(“from Customer as c”).list(); as关键字用来设置别名,as也可以省略。 from Customer c即可。
(3)================= HQL语句选择查询 ====================
选择查询是指仅查找某些属性。
这时list()返回的集合中包括的是一个一个数组,每个数组中是一条记录。
List <Object[]> customerlist=session.createQuery("select id,name from Customer").list();
for(Object[] obj:customerlist){
System.out.println(Arrays.toString(obj));
}
(4)================= HQL语句投影查询 ====================
基于选择查询的基础上,把查询到的属性封装到对象中,该对象的其他属性为null。
该对象必须有对应的构造方法。
List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer").list();
for(Customer c:customerlist){
System.out.println(c.toString());
}
Customer类中必须有如下构造方法
public Customer(Integer id, String name) {
this.id = id;
this.name = name;
}
(5)================= HQL对查询结果排序 ====================
HQL语言使用order by关键字对结果进行排序。
asc为升序,desc为降序。
List <Customer> customerlist=session.createQuery("select new Customer(id,name) from Customer order by id desc").list();
(6)================= HQL分页查询 ====================
-setFirstResult(int index):设定从第几个对象开始检索,起始值为0。
-setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。
Query query=session.createQuery("select id,name from Customer");
//从第一个对象开始
query.setFirstResult(0);
//查找两个对象
query.setMaxResults(2);
List result=query.list();
(7)================= HQL语句中绑定参数 ====================
对于实际应用中,经常需要用户输入一些查询条件,我们返回符合查询条件的数据。 我们可以使用from Customer where name='"+name+"';来实现 但是这种方式是非常不安全的,会受到SQL注入等非法攻击。
Hibernate中使用参数绑定来避免以上问题。有两种方式
(1)使用?占位符绑定
占位符的索引从0开始。
Query query=session.createQuery("from Customer where id=?");
query.setInteger(0, 7);
Customer c=(Customer) query.uniqueResult();
System.out.println(c.toString());
Query提供了各种绑定数据类型的参数的方法setXxx(),如果参数为字符串类型,就调用setString(),如果参数为整数类型,就调用setInteger()等等。
这些setXxx()方法第一个参数代表占位符的索引,第二个代表参数值。
(2) 使用参数名字绑定
在HQL中使用命名参数,命名参数以":"开头。
Query query=session.createQuery("from Customer where id=:a");
query.setInteger("a", 7);
Customer c=(Customer) query.uniqueResult();
System.out.println(c.toString());
这些setXxx()方法第一个参数是命名参数的名字,第二个参数是值。
(8)================= HQL查询单个对象 ====================
-uniqueResult()方法:返回单个对象
Query query=session.createQuery("from Customer where id=1");
Customer c=(Customer) query.uniqueResult();
System.out.println(c.toString());
(9)================= HQL聚合函数和分组查询 ====================
(1)HQL调用聚合函数
-查询customer表所有记录数目
Query query=session.createQuery("select count(*) from Customer");
//该语句返回long类型
Long c=(Long) query.uniqueResult();
System.out.println(c.intValue());
-查询最大ID
Query query=session.createQuery("select Max(id) from Customer");
Integer c=(Integer) query.uniqueResult();
System.out.println(c.intValue());
(2)分组查询
group by子句用来分组查询。
-根据id分组,统计相同id的数目
Query query=session.createQuery("select id,count(*) from Customer group by id");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-having子句用于为分组查询加上条件
Query query=session.createQuery("select id,count(*) from Customer group by id having id>8");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
(10)================= HQL连接查询 ====================
-交叉连接:返回被连接的两个表所有数据行的笛卡儿积
如果A表有5行记录,B表有7行记录,返回的结果就有35行记录
显然,会产生很多没有意义的数据。
Query query=session.createQuery("from Customer,Order");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-隐式内连接
在交叉连接基础上,通过条件来过滤一些无意义的数据,达到内连接的效果。
Query query=session.createQuery("from Customer c,Order o where o.customer=c");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-显式内连接
使用inner join关键字表示内连接。inner可以省略,只使用join。
调用list()方法返回的集合中存放的是每个元素对应的记录,每个元素都是数组类型。
Query query=session.createQuery("from Customer c inner join c.orders");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-迫切内连接
使用inner join fetch关键字表示迫切内连接。
调用list()方法返回的集合中存放的是Customer对象的引用,每个Customer对象的Orders集合都被初始化,存放所有关联的Order对象。
Query query=session.createQuery("from Customer c inner join c.orders");
List <Object> list=query.list();
for(Object obj:list){
System.out.println(obj);
}
-左外连接
在连接查询中,连接左端的表中的所有的行全部显示,并且能在右端的表中找到匹配的行,如果右端表中没能找到左端匹配的行,则对应NULL.
使用left join关键字表示左外连接。
返回的list集合中存放的是多个对象数组。
Query query=session.createQuery("from Customer c left join c.orders");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-迫切左外连接
使用left join fetch关键字表示迫切左外连接。
list()方法返回的集合中存放的是Customer对象的引用,每个Customer的Orders集合都被初始化,存放关联的Order对象。
Query query=session.createQuery("from Customer c left join fetch c.orders");
List<Object> list=query.list();
for(Object obj:list){
System.out.println(obj);
}
-右外连接
和左外连接一样,连接右端表中的行全部显示,连接左端找到匹配的行,如果未能找到匹配的行,则用NULL代替
使用right join关键字表示右外连接。
Query query=session.createQuery("from Customer c right join c.orders");
List<Object[]> list=query.list();
for(Object[] obj:list){
System.out.println(Arrays.toString(obj));
}
-迫切右外连接
Query query=session.createQuery("from Customer c right join fetch c.orders");
List<Object> list=query.list();
for(Object obj:list){
System.out.println(obj);
}
(11)================= 在映射文件中定义命名查询语句 ====================
前面的例子中,HQL查询语句都写在程序代码中。Hibernate允许在映射文件中定义字符串形式的查询语句。
<class name="com.cad.domain.Customer" table="customer" >
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<set name="orders" batch-size="3" fetch="subselect">
<key column="cid"/>
<one-to-many class="com.cad.domain.Order" />
</set>
<!--定义局部命名查询语句-->
<query name="bcd"><![CDATA[from Order]]></query>
</class>
<!--定义全局命名查询语句-->
<query name="abc"><![CDATA[from Customer]]></query>
//调用全局的命名查询语句
Query query=session.getNamedQuery("abc");
//调用局部的命名查询语句
Query query=session.getNamedQuery("com.cad.domain.Customer.bcd");
List<Object> list=query.list();
for(Object obj:list){
System.out.println(obj);
}
四、QBC检索方式
使用QBC(Query By Criteria)API检索对象。封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
QBC检索方式的步骤
-调用Session的createCriteria()方法创建一个Criteria对象
-设定查询条件
-调用Criteria接口的list()方法执行查询语句。返回List集合。
(1)================= 查询所有对象 ====================
//传递类名.class即可
Criteria criteria=session.createCriteria(Customer.class);
List<Customer> l=criteria.list();
for(Customer c:l){
System.out.println(c);
}
(2)================= QBC对查询结果进行排序 ====================
QBC使用org.hibernate.criterion.order类对查询结果排序。
asc为升序,desc为降序。
Criteria criteria=session.createCriteria(Customer.class);
criteria.addOrder(org.hibernate.criterion.Order.desc("id"));
List<Customer> l=criteria.list();
for(Customer c:l){
System.out.println(c);
}
(3)================= QBC分页查询 ====================
QBC的分页查询和HQL类似。Criteria接口也提供了方法。
-setFirstResult(int index):设定从第几个对象开始检索,起始值为0。
-setMaxResult(int count):设定一次检索的对象数目。默认情况下检索所有的对象。
Criteria criteria=session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(2);
List<Customer> l=criteria.list();
for(Customer c:l){
System.out.println(c);
}
(4)================= QBC设定查询条件 ====================
必须创建一个Criterion对象来设定查询条件。Restrictions类提供了创建Criterion的方法。
-Restrictions.eq() 等于
-Restrictions.ne() 不等于
-Restrictions.gt() 大于
..........等等很多方法
Criteria criteria=session.createCriteria(Customer.class);
//查询id为7的Customer
Criterion c1=Restrictions.eq("id", 7);
criteria.add(c1);
Customer c=(Customer) criteria.uniqueResult();
System.out.println(c);
(5)================= QBC检索单个对象 ====================
uniqueResult():返回单个对象
五、本地SQL检索方式
可以使用原生的SQL语句来进行查询。
本地SQL检索也是使用Query接口,通过Session的createSQLQuery(SQL语句)方法来创建Query。
例子:
Query query =session.createSQLQuery("select * from customer");
List<Object[]> list=query.list();
for(Object[] o:list){
System.out.println(Arrays.toString(o));
}
默认情况下,SQLQuery返回的list集合中存放的是关系数据。每个元素都是Object[]数组。
-addEntity()方法能把查询结果中每一行的数据封装成对象
Query query =session.createSQLQuery("select * from customer").addEntity(Customer.class);
List<Customer> list=query.list();
for(Customer o:list){
System.out.println(o.toString());
}

浙公网安备 33010602011771号