一、hibernate的查询方式
1.对象导航查询
根据id查询某个客户,再查询这个客户里面的所有联系人
@Test
public void testSelect1(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
//1.查询id为1的客户,再查询这个客户里面所有的联系人
Customer customer = session.get(Customer.class, 1);
Set<LinkMan> linkman = customer.getSetLinkMan();
System.out.println(linkman.size());
transaction.commit();
}catch(Exception e){
transaction.rollback();
e.printStackTrace();
}finally{
session.close();
sessionFactory.close();
}
}
2.OID查询
根据id查询某一条记录,返回对象
Customer customer = session.get(Customer.class, 1);
3.hql查询
Query对象,hql语句
(1)查询所有 from+实体类名
@Test
public void testSelect3(){
SessionFactory sessionFactory = null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
transaction = session.beginTransaction();
//1.创建query对象
Query query = session.createQuery("from Customer");
//2.调用方法
List<Customer> list = query.list();
for(Customer c : list){
System.out.println(c.getCustName());
}
transaction.commit();
}catch(Exception e){
transaction.rollback();
e.printStackTrace();
}finally{
session.close();
sessionFactory.close();
}
}
(2)条件查询
//from 实体类名称 where 实体类属性名称 = ? and 实体类属性名称 = ?
//1.创建query对象
Query query = session.createQuery("from Customer C WHERE C.custName = ?0");
//设置参数
//query.setString(0, "web");
query.setParameter(0, "web");
//2.调用方法
List<Customer> list = query.list();
//from 实体类名称 where 实体类属性名称 like ?
Query query1 = session.createQuery("from Customer C WHERE C.custName like ?0");
query1.setParameter(0, "%度%");
List<Customer> list1 = query1.list();
(3)排序查询
from 实体类名称 order by 实体类属性名称 asc/desc
(4)分页查询
//1.使用关键字limit实现
SELECT * FROM t_customer LIMIT 0,3
//2.在hql中,在语句中不能使用limit,使用query对象封装的两个方法实现
//1.创建query对象,写查询所有的语句
Query query = session.createQuery("from Customer");
//2.设置分页数据
//2.1 设置开始位置
query.setFirstResult(0);
//2.2 设置每页记录数
query.setMaxResults(3);
//3.调用方法得到结果
List<Customer> list = query.list();
for(Customer customer : list){
System.out.println(customer.getCid()+"-"+customer.getCustName());
}
(5)投影查询
查询不是所有字段值,而是部分字段的值
//select 实体类属性名称1,实体类属性名称2 from 实体类名称
//1.创建query对象,select后面不能写*
Query query = session.createQuery("select cid,custName from Customer");
//2.调用方法得到结果
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(objects[0]+" - "+objects[1]);
}
(6)聚集函数使用
常用的聚集函数,count、sum、avg、max、min
//1.创建query对象
Query query = session.createQuery("select count(*) from Customer");
//2.调用方法得到结果
//uniqueResult()方法返回一个Long类型值
Object obj = query.uniqueResult();
Long lobj = (Long)obj;
int iobj = lobj.intValue();
System.out.println(iobj);
4.QBC查询
Criteria对象,方法实现,不需要写语句。操作的是实体类和属性
(1)查询所有
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.调用方法
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid() + " " + customer.getCustName());
}
(2)条件查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.调用方法设置条件值
//首先使用add方法,在里面使用类的方法实现条件设置
//类似于cid=?,custLevel=?
criteria.add(Restrictions.eq("cid", 1));
criteria.add(Restrictions.eq("custLevel", "pp"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid() + " " + customer.getCustName());
}
//模糊查询 like()方法
criteria.add(Restrictions.like("custName", "%百%"));
(3)排序查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.调用方法,设置对哪个属性进行排序以及排序规则
criteria.addOrder(Order.desc("cid"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid() + " " + customer.getCustName());
}
(4)分页查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.调用方法设置分页数据
//设置开始位置,当前页计算公式:(当前页-1)*每页记录数
criteria.setFirstResult(0);
//设置每页显示数据数
criteria.setMaxResults(3);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid() + " " + customer.getCustName());
}
(5)统计查询
//1.创建对象
Criteria criteria = session.createCriteria(Customer.class);
//2.设置操作
criteria.setProjection(Projections.rowCount());
Object obj = criteria.uniqueResult();
Long lobj = (Long)obj;
int count = lobj.intValue();
System.out.println(count);
(6)离线查询
//1.创建对象
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
//2.最终执行时用到session
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<Customer> list = criteria.list();
(7)多表查询
MySQL中实现
·内连接
·左外连接
·右外连接
HQL实现
·内连接
Query query = session.createQuery("from Customer c inner join c.setLinkMan");
//返回额list里面为Object[]数组
List list = query.list();
·左外连接
Query query = session.createQuery("from Customer c left outer join c.setLinkMan");
//list集合中每部分是数组
List list = query.list();
·右外连接
Query query = session.createQuery("from Customer c right outer join fetch c.setLinkMan");
List list = query.list();
·迫切内连接
与内连接的底层实现一致,但返回的list集合中每部分不是数组,而是对象
Query query = session.createQuery("from Customer c inner join fetch c.setLinkMan");
List list = query.list();
·迫切左外连接
Query query = session.createQuery("from Customer c left outer join fetch c.setLinkMan");
//list集合返回的是对象
List list = query.list();
5.本地sql查询
SQLQuery对象,使用普通sql实现
二、Hibernate的检索策略
1.立即查询
2.延迟查询
// 一调用get方法,就马上发送sql语句,成为立即查询
Customer customer = session.get(Customer.class, 1);
System.out.println(customer.getCustName()+" "+customer.getCid());
// 调用load方法后不会马上发送sql语句
Customer customer1 = session.load(Customer.class, 2);
// 返回的对象中包含id值,此时也不发送sql语句
System.out.println(customer1.getCid());
// 使用对象中非id值时才发送sql语句
System.out.println(customer1.getCustName());
延迟查询又分成两类:
(1)类级别延迟
(2)关联级别延迟:查询某个客户,再查询这个客户下的所有联系人,查询联系人的过程是否需要延迟,这个过程称为关联级别查询
//先查询id为1的客户,再查询这个客户里面的所有联系人
Customer customer = session.get(Customer.class, 1);
//得到set集合,没有发送语句
Set<LinkMan> set = customer.getSetLinkMan();
//使用这个set集合时,发送语句
System.out.println(set.size());
3.关联级别延迟操作
(1)在映射文件中进行配置
根据客户得到所有联系人,在客户映射文件中配置,在set标签上使用fetch和lazy属性。
//默认情况下,延迟查询
fetch="select" lazy="true"
//select-false,get方法查询联系人时就发送了两条语句,把联系人和set集合都查出来了,效率低一般不用
fetch="select" lazy="false"
//select-extra,极其懒惰,效率高,需要什么查询什么
fetch="select" lazy="extra"
4.批量抓取
查询所有客户,返回list集合,遍历list集合,得到每个客户,得到每个客户所有联系人。
//查询所有客户
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
//得到每个客户里面的联系人
for (Customer customer : list) {
System.out.println("客户姓名:" + customer.getCustName());
Set<LinkMan> setLinkMan = customer.getSetLinkMan();
for (LinkMan linkMan : setLinkMan) {
System.out.println("联系人姓名:" + linkMan.getLkm_name());
}
}
上面代码可以实现,但是效率很低,每次遍历都进行了一次查询。
使用批量抓取优化,在客户的映射文件中,配置set标签,使用batch-size属性,值越大,效率越高。
<set name="setLinkMan" batch-size="10">