Hibernate的查询方式
Hibernate提供了5种查询方式:
1.OID查询
根据对象OID(主键)进行检索,使用get方法;使用load方法。
2.对象导航查询
根据一个已查询到的对象,获得关联对象。
LinkMan linkMan = session.get(LinkMan.class, 1l);
Customer customer = linkMan.getCustomer();//根据查询对象获得关联对象
3.HQL检索
HIbernate Query Language ,Hibernate的查询语言,是一种面向对象的查询方式语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询的方式。
HQL查询所有使用:from 表名; 而不使用select * from 表名; 应为HQL不能直接查询* 但是可以查询COUNT(*)查询到的是Long类型的值。
我们首先创建一张一对多的表:
基本查询
@Test//HQL的简单查询
public void test2(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Query query = session.createQuery("from Customer");
//也可取别名查询,别名查询可以select c.cust_name from Customer c
// Query query2 = session.createQuery("select c from Customer c");//第二个c是别名
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
排序查询
@Test//排序查询
public void test3(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// Query query = session.createQuery("from Customer order by cust_id asc");//asc是升序,默认值可不写
Query query2 = session.createQuery("from Customer order by cust_id desc");//desc是降序
List<Customer> list = query2.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
条件查询
一、按位置绑定:根据参数位置进行绑定
//查询姓名以杨开头,来源是网络的对象customer
Query query = session.createQuery("from Customer where cust_name like ? and cust_source=?");
query.setParameter(0, "杨%");
query.setParameter(1, "网络");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
二、按名称绑定
//按名称绑定,查询姓名以杨开头,来源是网络的对象customer
Query query = session.createQuery("from Customer where cust_name like :suibianqi and cust_source= :suibianjiao");
query.setParameter("suibianqi", "杨%");
query.setParameter("suibianjiao", "网络");
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
投影查询:查询对象的某个或某些属性
//查询出数组
List<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
//查询出并封装对象:需要在实体只提供对应的有参构造
List<Customer> list2 = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list();
for (Customer customer : list2) {
System.out.println(customer);
}
查出的数组:
查出的对象:
分页查询
//从第20个记录开始,查询10条记录
Query query = session.createQuery("from LinkMan");
query.setFirstResult(20);
query.setMaxResults(10);
List<LinkMan> list = query.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
聚合函数&分组统计
//聚合函数:COUNT(),MAX(),MIN(),AVG(),SUM()
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object);
//分组统计:按照来源分组,筛选出总数大于等于1的来源
List<Object[]> list = session.createQuery("select cust_source,count(*) from Customer group by cust_source having count(*)>=1").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
HQL多表查询
分为内连接、迫切内连接、左外连接、右外连接、迫切左外连接。
迫切连接时给普通连接的join后面加上fetch,作用是:普通连接查询结果是一个对象数组,迫切连接查询结果将附表封装成到主表,将查询结果封装成一个对象。关于内连接和外连接的概念:https://blog.youkuaiyun.com/weixin_38930706/article/details/81157775#t36
//普通内连接:封装成数组
List<Object[]> list = session.createQuery("from Customer c inner join c.linkMans").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();
for (Customer customer : list) {//toString方法加上linkMans
System.out.println(customer);
}
select distinct c 可以把重复的查询结果删除。
4.QBC检索
Query By Criteria 标准查询。是一种更加面向对象化的查询方式,连查询语句都不用写。直接调用对象中的方法进行设置。
简单查询
@Test//简单查询
public void test1(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
排序查询
@Test //排序查询
public void test2(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.asc("cust_id"));//升序(默认)
criteria.addOrder(Order.desc("cust_id"));//降序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
分页查询
@Test//分页查询
public void test3(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(20);
criteria.setMaxResults(10);
List<LinkMan> list = criteria.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
}
transaction.commit();
}
条件查询
条件查询设置条件:
= | > | >= | < | <= | <> | like | or | and | in |
eq | gt | ge | lt | le | ne | like | or | and | in |
条件查询多多条criteria.add()之间是and关系。
@Test//条件查询
public void test4(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
criteria.add(Restrictions.eq("cust_source", "小广告"));
criteria.add(Restrictions.like("cust_name", "李%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
统计查询
@Test//统计查询
public void test5(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
criteria.setProjection(Projections.rowCount());//这种查询可以查询:聚合函数 和 group by having
Object num = criteria.uniqueResult();
System.out.println(num);
transaction.commit();
}
离线条件查询(SSH)
离线条件查询的对象是DetachedCriteria,它更适合做综合条件查询。
@Test//离线条件查询
public void test6(){
DetachedCriteria detachedCriteria =DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.like("cust_name", "李%"));
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
Criteria criteria = detachedCriteria.getExecutableCriteria(session);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
5.SQL检索
@Test//SQL查询
public void test1(){
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
/* //查询结果封装到Object[]中
List<Object[]> list = sqlQuery.list();*/
//查询结果封装到Customer对象中
sqlQuery.addEntity(Customer.class);
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
}
transaction.commit();
}
SQL查询已经不常用了,但是调优还是方便的。
Hibernate抓取策略
抓取策略是对hibernate进行性能调优的手段。
首先了解延迟加载:延迟加载分为 类延迟加载 和 关联级别的延迟加载
类延迟加载的开启和关闭可以在类对应的hibernate映射配置文件中的<class>标签中加入属性lazy="true" 和 lazy="false"。关闭延迟加载的话load()方法和get()方法的作用一样了,会立即发送查询语句。
类级别加载如何让lazy失效?
1.lazy="false"
2.将持久化类用final修饰
3.Hibernate.initialize(obj)
关联级别的延迟加载在一对多的关系中还需要添加标签属性lazy="true" 和 lazy="false"到:一的一方到<set>;多的一方到<many-to-one>。<class>中的lazy只会对<property>中的属性起作用。
抓取策略往往会和关联级别的延迟加载一起使用来优化语句。
抓取策略的概述
- 通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。
- 通过<set>或者<many-to-one>上通过fetch属性进行设置
- fetch和这些标签上的lazy如何设置优化发送的SQL语句
- <set>上的fetch和lazy
- fetch:抓取策略,控制SQL语句格式
- select :默认值,发送普通的select语句,查询关联对象
- join :发送一条迫切左外连接查询关联对象
- subselect :发送一条子查询查询其关联对象
- lazy:延迟加载,控制查询关联对象的时候是否采用延迟
- true :默认值,查询关联对象的时候,采用延迟加载
- false :查询关联对象的时候,不采用延迟加载
- extra :及其懒惰。
- 在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。
-
-
- <many-to-one>上的fetch和lazy
-
-
- fetch :抓取策略,控制SQL语句格式。
- select :默认值,发送普通的select语句,查询关联对象。
- join :发送一条迫切左外连接。
- lazy :延迟加载,控制查询关联对象的时候是否采用延迟。
- proxy :默认值,proxy具体的取值,取决于另一端的<class>上的lazy的值。
- false :查询关联对象,不采用延迟。
- no-proxy :(不会使用)
- 在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join。