【Hibernate】Hibernate的检索方式:OID、HQL、QBC

检索方式

1)导航对象图检索方式

customer.getOrders().iterator();


2)OID检索方式

session.get()、load();


3)HQL检索方式

// 创建Query对象
Query q = session.createQuery("from Customer as c where c.name=:name");
// 动态绑定参数
q.setString("name", "tom");
// 执行查询语句
q.list();

只需要提供面向对象的HQL查询语句,Hibernate就能根据映射文件的配置,将HQL转换为SQL,并将JDBC ResultSet结果集映射为关联的对象图。


注意,如果写了select ... from,则返回的是关系数据,而非持久化对象!

当然,可以用JavaBean将这些关系数据封装起来。


4)QBC检索方式

Query By Criteria

// 创建Criteria对象
Criteria criteria = session.createCriteria(Customer.class);

//设定查询条件
Criteria criteria1 = Restrictions.like("name", "T%");
Criteria criteria2 = Restrictions.eq("age", new Integer(21));

criteria = criteria.add(criteria1)
                   .add(criteria2);

// 执行查询语句
criteria.list();

QBC还提供了一种QBE子功能( Query by Example),能够把exampleCustomer对象中所有不为null的属性作为查询条件:

......
exampleCustomer.setAge(21);
session.createCriteria(Customer.class)
       .add(Example.create(exampleCustomer))
       .list();
类似于Query的setProperties:

session.createQuery(from customer where age=:age and name=:name)
       .setProperties(exampleCustomer)
       .list();

5)本地SQL检索方式

Query q = session.createSQLQuery("select * from CUSTOMERS where ....");
q.setString(...);
q.list();

注意:返回的是关系数据;可用addEntity()来将关系数据映射为对象:

Query q = session.createSQLQuery("select * from CUSTOMERS where ....").addEntity(Customer.class)

方法

使用别名

HQL:

session.createQuery("from Customer as c");

QBC:

不需要显式指定别名,Hibernate会自动把查询语句的根节点赋予别名“this”

session.createCriteria(Customer.class)

              .add(Restrictions.eq("this.name", "tom"))

              .list();


排序

HQL:

session.createQuery("from Customer as c order by c.name asc, c.age desc");

QBC:

session.createCriteria(Customer.class).addOrder(Order.asc("name"))

                                                                        .addOrder(Order.desc("age"));


多态查询

HQL和QBC支持多态查询,能查询出当前类及其所有子类实例。


分页查询

query.setFirstResult(97);

query.setMaxResults(10);

query.list();


Criteria类似。


动态查询

HQL与QBC都能完成相同的任务,HQL更加直观简洁;那Criteria适用于什么场景呢?

例如根据用户输入的姓名和年龄来查询Customer,

HQL要包含大量的逻辑判断:

StringBuffer hql = new StringBuffer("from Customer c");
if (name != null){
    hql.append(" where lower(c.name) like :name");
}
......

而QBC可简化这种逻辑判断:
Criteria c = session.createCriteria(Customer.class);
if(name != null){
    c.add(
        Restrictions.like("name", name.toLowerCase(), MatchMode.ANYWHERE) );
}
......

也可以使用QBE:
Example exampleCustomer  = Example.create(customer);
exampleCustomer.ignoreCase().enableLike(MatchMode.ANYWHERE);
exampleCustomer.excludeZeroes();

Criteria c = session.createCriteria(Customer.class).add(exampleCustomer);
c.list();


子查询

from Customer c where 1 < 
   (select count(o) from c.orders o)

HQL对集合提供了一组函数/属性,例如size、size()、elements()
from Customer c where c.orders.size > 0 --size
from Customer c where size(c.orders) > 0 --size()

session.createQuery("from Customer c where :order in elments(c.orders)") --elements()
    .setEntity("order", order)
    .list();

检索单个对象

session.createQuery(.....)

               .setMaxResults(1)

               .uniqueResult();

Criteria类似。

如果query包含多个对象,但没有调用setMaxResults(1),则会抛出NonUniqueResultException。——?

确保查询结果不含重复实例

可用LinkedHashSet来包装查询结果,去除重复对象

Set distinctResults = new LinkedHashSet(query.list() );

Query.iterate()

和list功能一样,但使用的查询机制不同:

list会返回对象的所有属性,而iterate则只返回ID属性

Iterator customers = query.iterate();
while(customers.hasNext()){
    Customer cus = (Customer) customers.next(); //1
    String name = cus.getName();
}
执行到customers.next()时,先查session缓存,如果缓存中已存在该对象,则直接返回;若不存在,则查询数据库(返回所有属性)

适用场景:

  1. CUSTOMERS表中有大量字段
  2. 启用了二级缓存,并且缓存中可能已包含待查询的Customer对象


Query.setReadOnly()

默认情况下,如果对查询到的对象的属性做了修改,则当Hibernate清理缓存时,会去同步更新回数据库。

如果要只允许读取属性值,而不允许更新属性值,可用setReadOnly().


与检索策略的综合运用

1)Query中指定检索策略

Q:Query会忽略xml中配置的迫切左外连接策略;那么如何在Query中运用迫切左外连接?

A:可以在HQL查询语句中显式指定检索策略:

// left join fetch
String hql = "from Customer c left join fetch c.orders o where c.name like 'T%' ";
Query query = session.createQuery(hql);
query.list();


2)Criteria中指定检索策略

其实在QBC中也可以显式指定检索策略:

Criteria c = session.createCriteria(Customer.class)
    .addFetchMode("orders", FetchMode.JOIN)
    .add(Restrictions.like("name", "T", MatchMode.START));
c.list();

  • FetchMode.DEFAULT:默认值,采用映射文件中配置的检索策略;
  • FetchMode.JOIN:迫切左外连接检索策略;
  • FetchMode.SELECT:采用映射文件中配置的检索策略,并通过单独的select语句检索关联的对象,相当于fetch = select












你可能感兴趣的:(Hibernate)