您的位置:首页 > 其它

HQL数据查询基础(三)

2016-05-20 12:00 453 查看
       继上回 (HQL数据查询基础(二)),针对“网上商店”这个例子,来讲解一些HQL简单的子句用法。

(以下的所有测试方法均在 MyTest.java 测试类(在上文上有提到)中添加)

from子句

1)HQL语句最简形式;

2)from指定了HQL语句查询主体——持久化类及其属性

from子句中持久化类的引用

1)不需要引入持久化类的全限定名,直接引入类名;

2)auto-import(自动引入)缺省情况。

测试from子句的使用——获取customer表中的所有客户信息:
<span style="font-size:18px;">@Test
public void testFromClause1() {
String hql = " from Customer ";
//创建Query实例对象
Query query = session.createQuery(hql);
List<Customer> customers = query.list();

for(Customer customer : customers) {
System.out.println("name: " + customer.getName());
}
}</span>


测试能否通过 商品对象 获得 商家信息:
<span style="font-size:18px;">/**
* 测试能否通过 商品对象 获取 商家信息
*/
@Test
public void testFromClause2() {
String hql = " from Commodity ";

Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();

for (Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("seller's name: " + c.getSeller().getName());
}
}</span>


       Hibernate中默认是“懒”加载状态,只有需要到某些关联信息才进行查询。在这个例子中,我们先查询到所有商品信息,根据商品信息获取商家信息,获取商家信息的时候Hibernate才发起查询,并不是在查询到商品信息的同时也查询了商家信息。Hibernate做了延迟加载。

from子句中别名的应用
1)为被查询的类指定别名;
2)在HQL语句其他部分通过别名引用该类;
3)别名命名习惯:一般与持久类类名相同,使用小写。如:from Seller 中 Seller 别名可以为 seller,为了简洁,别名也可以取名为 s。在简洁的同时,需要保证代码的可读性。
具体如: from Seller as seller 或 from Seller as s 或 from Seller seller 或 from Seller s(as 关键字可以省略)


select子句

1)select子句中未指定返回数据类型,默认为Object[];(注意:当查询的字段只有一个时,返回的数据类型就不再是 Object[],而是Object)
测试select子句的Object[] 返回数据类型:
<span style="font-size:18px;">/**
* 1. name 2.tel 3.address 4.star
*/
@Test
public void testSelectClauseObjectArray() {
String hql = "select s.name, s.tel, s.address, s.star from Seller s ";

Query query = session.createQuery(hql);
List<Object[]> list = query.list();

for(Object[] objs : list) {
System.out.println("name: " + objs[0]);
System.out.println("tel: " + objs[1]);
System.out.println("address: " + objs[2]);
System.out.println("star: " + objs[3]);
}

System.out.println();
System.out.println("特殊实例:");

//如果查询的字段只有一个的话,那么其返回类型是 Object 而不是Object[]。
String hql2 = "select s.name from Seller s ";

Query query2 = session.createQuery(hql2);
List<Object> list2 = query2.list();

for(Object objs : list2) {
System.out.println("name: " + objs);
}
}</span>


2)以List形式返回查询结果——select子句中使用new list指定;
测试select子句的 List 返回数据类型:
<span style="font-size:18px;">    @Test
public void testSelectClauseList() {
String hql = "select new list(s.name, s.tel, s.address) from Seller s";
Query query = session.createQuery(hql);
List<List> lists = query.list();

for(List list : lists) {
System.out.println("name: " + list.get(0));
System.out.println("tel: " + list.get(1));
System.out.println("address: " + list.get(2));

}
}</span>


3)以Map形式返回查询结果——select子句中使用new map指定,key值为索引值,字符串类型;
测试select子句的 Map返回数据类型:
<span style="font-size:18px;">    @Test
public void testSelectClauseMap() {
String hql = "select new map(s.name, s.tel, s.address) from Seller s";
Query query = session.createQuery(hql);
List<Map> maps = query.list();

for(Map map : maps) {
System.out.println("name: " + map.get("0"));
System.out.println("tel: " + map.get("1"));
System.out.println("address: " + map.get("2"));
}

//除了通过序号来获取查询结果外,还可以使用别名来获取
String hql2 = "select new map(s.name as name, s.tel as tel, s.address as address) from Seller s";
Query query2 = session.createQuery(hql2);
List<Map> maps2 = query2.list();

for(Map map : maps2) {
System.out.println("name: " + map.get("name"));
System.out.println("tel: " + map.get("tel"));
System.out.println("address: " + map.get("address"));
}
}</span>


4)以自定义类型返回查询结果——持久化类中定义对应的构造器,构造器的参数就是我们选择返回的属性信息;select子句中调用定义的构造器来完成相应的查询,以自定义类型来返回查询的结果
测试select子句中以自定义类型返回查询结果:
        需要我们在查询类中添加自定义的构造方法,本次查询的类为 Seller类,我们需要在Seller类中自定义构造方法,而构造方法中的参数就是我们需要查询返回的信息:
public Seller(String name, String tel, String address) {
this.name = name;
this.tel = tel;
this.address = address;
}

测试方法如下:
@Test
public void testSelectClauseSelf() {
String hql = "select new Seller(s.name, s.tel, s.address) from Seller s";
Query query = session.createQuery(hql);
List<Seller> sellers = query.list();
for(Seller seller :sellers) {
System.out.println("name: " + seller.getName());
System.out.println("tel: " + seller.getTel());
System.out.println("address: " + seller.getAddress());
}
}

注:当我们自定义了构造方法之后,还需要定义无参的构造方法吗?答案是肯定的。我们先来回顾一下之前定义的一个测试方法testSeller:
@Test
public void testSeller() {
String hql = " from Seller s";
//创建Query实例对象
Query query = session.createQuery(hql);
List<Seller> sellers = query.list();

for(Seller seller : sellers) {
System.out.println(seller);
}
}

这里并未使用到select子句,那么默认返回的是所有Seller的所有属性信息,它此时调用的无参构造方法。如果我们不提供默认的无参构造方法的话,执行上面的测试方法,将出现 没有找到 Seller 实体的错误提示。
所以我们需要在自定义构造方法后,在类中同样增加无参的构造方法。

distinct 关键字
使用distinct关键字去除查询结果中的重复元素
测试使用distinct关键字,消除结果集中重复的元素:
@Test
public void testDistinct() {
String hql = "select distinct c.sex from Customer c";
Query query = session.createQuery(hql);
List<Object> list = query.list();
for(Object obj : list) {
System.out.println(obj);
}
}


where子句
我们可以通过where子句设置查询条件,限制返回结果。
(1)比较运算
1. = 、<> 、< 、> 、>= 、<=
2.null值判断——is [not] null,在HQL中可使用 = null 或 <> null 来表示 is [not] null
测试使用比较运算符:
@Test
public void testWhere1() {
String hql = " from Commodity c where c.price > 400";
Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();
for(Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("price: " + c.getPrice());
}
}

测试null值判断:
@Test
public void testWhere2() {
//is null 的判断
//String hql = " from Commodity c where c.description is null";
//String hql = " from Commodity c where c.description = null";
//is not null 的判断
//String hql = " from Commodity c where c.description is not null";
String hql = " from Commodity c where c.description <> null";

Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();
for(Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("description: " + c.getDescription());
}
}


(2)范围运算
1. [not] in(列表);
2. [not] between 值1 and 值2
测试:
@Test
public void testWhere3() {
//String hql = " from Customer c where c.age in(20, 40)";
//String hql = " from Customer c where c.age not in(20, 40)";
//String hql = " from Customer c where c.age between 20 and 40";
String hql = " from Customer c where c.age not between 20 and 40";
Query query = session.createQuery(hql);
List<Customer> customers = query.list();
for(Customer c : customers) {
System.out.println("name: " + c.getName());
System.out.println("age: " + c.getAge());
}
}


(3)字符串模式匹配
1、like关键字;
2、通配符 %、_ (%:任意个字符;_:一个字符)
测试:
@Test
public void testWhere4() {
//String hql = " from Customer c where c.name like '张_'";
String hql = " from Customer c where c.address like '%北京%'";
Query query = session.createQuery(hql);

List<Customer> customers = query.list();
for(Customer c : customers) {
System.out.println("name: " + c.getName());
System.out.println("address: " + c.getAddress());
}
}


(4)逻辑运算
1、and(逻辑与)、or(逻辑或)
2、not(逻辑非)
测试:
@Test
public void testWhere5() {
//String hql = " from Commodity c where c.price between 100 and 5000 and c.category like '%电脑%'";
String hql = " from Commodity c where c.price between 100 and 5000 or c.category like '%电脑%'";
Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();
for(Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("category: " + c.getCategory());
System.out.println("price: " + c.getPrice());
}
}


(5)集合运算
1、is [not] empty 集合[不]为空,不包含任何元素;
2、member of 元素属于集合;
测试:
@Test
public void testWhere6() {
//查询订单信息不为空的有效订单
String hql = " from Order o where o.orderItems is not empty";
Query query = session.createQuery(hql);
List<Order> orders = query.list();
for(Order order : orders) {
System.out.println(order.getCustomer().getName());
System.out.println(order.getAmount());
System.out.println(order.getTradeDate());
}
}


(6)四则运算
1、HQL语句中也可以使用 + - x / 四则运算
2、四则运算可以在where子句和select子句中使用
测试:
@Test
public void testWhere7() {
String hql = " from Commodity c where c.price * 5 > 3000";
Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();
for(Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("price: " + c.getPrice() * 5);
}
}


(7)查询单个对象
1、Query接口的uniqueResult方法;
2、where子句条件的设置,我们需要确保where子句设置的条件查询出来的结果只有一条数据或没有数据,否则使用uniqueResult方法过程中会抛出异常 org.hibernate.NonUniqueResultException: query did not return a unique result,中止运行。
测试:
@Test
public void testWhere8() {
//String hql = " from Customer c where c.name = '张三'";
String hql = " from Customer c where c.age > 20";
Query query = session.createQuery(hql);

Customer c = (Customer) query.uniqueResult();
System.out.println(c.getName());
}


排序——order by子句

使用order by子句对查询结果排序
1、升序排序 asc;2、降序排序 desc;
测试:
@Test
public void testOrderBy() {
//String hql = " from Commodity order by price asc";
//String hql = " from Commodity order by price desc";
String hql = " from Commodity order by seller.id asc, price desc, name asc";
Query query = session.createQuery(hql);
List<Commodity> commodities = query.list();
for(Commodity c : commodities) {
System.out.println("name: " + c.getName());
System.out.println("sellerId: " + c.getSeller().getId());
System.out.println("sellerName: " + c.getSeller().getName());
System.out.println("price: " + c.getPrice());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息