customer.getOrders().iterator();
session.get()、load();
// 创建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将这些关系数据封装起来。
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();
...... 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();
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"); } ......
Criteria c = session.createCriteria(Customer.class); if(name != null){ c.add( Restrictions.like("name", name.toLowerCase(), MatchMode.ANYWHERE) ); } ......
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)
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() );
和list功能一样,但使用的查询机制不同:
list会返回对象的所有属性,而iterate则只返回ID属性
Iterator customers = query.iterate(); while(customers.hasNext()){ Customer cus = (Customer) customers.next(); //1 String name = cus.getName(); }执行到customers.next()时,先查session缓存,如果缓存中已存在该对象,则直接返回;若不存在,则查询数据库(返回所有属性)
适用场景:
默认情况下,如果对查询到的对象的属性做了修改,则当Hibernate清理缓存时,会去同步更新回数据库。
如果要只允许读取属性值,而不允许更新属性值,可用setReadOnly().
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();
其实在QBC中也可以显式指定检索策略:
Criteria c = session.createCriteria(Customer.class) .addFetchMode("orders", FetchMode.JOIN) .add(Restrictions.like("name", "T", MatchMode.START)); c.list();