Hibernate--Hibernate检索方式

导航对象图检索方式

根据已经加载的对象导航到其他对象
样例:

 Order order=session.get(Order.class, 1);
  order.getCustomer();

OID 检索方式: 按照对象的 OID 来检索对象

Order order=session.get(Order.class, 1);
  order.getCustomer();

HQL 检索方式: 使用面向对象的 HQL 查询语言

测试案例:
1)永久化类

public class Employee {
 private Integer id;
 private String name;
 private float salary;
 private String email;
 private Department dept;}
public class Department {
 private Integer id;
 private String name;
 private Set<Employee> emps=new HashSet<>();}

2)实体关系配置表

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2020??4??19?? ????5:15:24 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.atguigu.hibernate.entities.Department" table="GG_DEPARTMENT">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <set name="emps" table="GG_EMPLOYEE" inverse="true" lazy="true">
            <key>
                <column name="DEPT_ID"/>
            </key>
            <one-to-many class="com.atguigu.hibernate.entities.Employee" />
        </set>
    </class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2020??4??19?? ????5:15:24 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping>
    <class name="com.atguigu.hibernate.entities.Employee" table="GG_EMPLOYEE">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        <property name="salary" type="float">
            <column name="SALARY" />
        </property>
        <property name="email" type="java.lang.String">
            <column name="EMAIL" />
        </property>
        <many-to-one name="dept" class="com.atguigu.hibernate.entities.Department">
            <column name="DEPT_ID" />
        </many-to-one>
    </class>
</hibernate-mapping>

##检索步骤
1)通过Session的createQuery()方法创建一个Query对象,它包括一个HQL查询语句.HQL查询语句中可以包含命名参数
2)动态绑定参数
3)调用Query相关方法执行查询语句
Qurey接口支持方法链编程风格,它的setXxx()方法返回自身实例,而不是void类型

绑定参数查询

Hibernate的参数绑定机制依赖于JDBCAPI中的PreparedStatement的预定义SQL语句功能。

按参数名字绑定

在HQL查询语句中定义命名参数,命名参数以“:”开头。

String hql="From Employee e WHERE e.salary> :salar ";
  //String hql="From Employee e";
  Query<Employee> query=session.createQuery(hql);
  query.setFloat("salar", 200.0f);
  //query.setParameter("salar", 200.0f);也可以运行
  List<Employee> emps=query.list();
  System.out.println(emps);

按参数位置绑定

在HQL查询语句中用“?”来定义参数位置

String hql="From Employee e WHERE e.salary> ? ";
Query<Employee> query=session.createQuery(hql);
//query.setParameter(0, 200.0f);报错
//query.setFloat(0, 200.0f);报错

在hibernate测试发现,参数查询设置参数对应的取值均报错。

分页查询

1)setFirstResult(intfirstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0.默认情况下,Query从查询结果中的第一个对象开始检索
2)setMaxResults(intmaxResults):设定一次最多检索出的对象的数目.在默认情况下,Query和Criteria接口检索出查询结果中所有的对象

String hql="From Employee";
  Query query=session.createQuery(hql);
  int pageNo=3;
  int pageSize=5;
  List<Employee> emps=query.setFirstResult((pageNo-1)*pageSize).setMaxResults(pageSize).list();
  System.out.println(emps);

在映射文件中定义命名查询语句

1)Hibernate 允许在映射文件中定义字符串形式的查询语句.
2)<query> 元素用于定义一个 HQL 查询语句, 它和 元素并列.
3)在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象
示例代码:
1)实体关系文件中配置

    <query name="salaryEmps">
     <![CDATA[FROM Employee e where e.salary>:minsal and e.salary<:maxSal]]>
    </query>
</hibernate-mapping>

2)代码测试

public void test() {
  Query query=session.getNamedQuery("salaryEmps");
  List<Employee> emps=query.setParameter("minsal", 800f).setParameter("maxSal", 6000f).list();
  System.out.println(emps.size());
 } 

投影查询

1)投影查询:查询结果仅包含实体的部分属性.通过SELECT关键字实现
2)Query的list()方法返回的集合中包含的是数组类型的元素,每个对象数组代表查询结果的一条记录

public void test() {
  String hql="select e.email,e.salary from Employee e where e.dept=:dept";
  Query query=session.createQuery(hql);
  Department dept=new Department();
  dept.setId(80);
  List<Object[]>result=query.setEntity("dept", dept).list();
  for(Object[] objs:result) {
   System.out.println(Arrays.asList(objs));
  }
 } 

3)可以在持久化
类中定义一个对象的构造器来包装投影查询返回的记录,使程序代码能完全运用面向对象的语义来访问查询结果集.

public void test() {
  String hql="select new Employee(e.name,e.salary,e.dept) from Employee e where e.dept=:dept";
  Query query=session.createQuery(hql);
  Department dept=new Department();
  dept.setId(10);
  List<Employee>result=query.setEntity("dept", dept).list();
  for(Employee emp:result) {
   System.out.println(emp.toString());
  }
 } 

4)可以通过DISTINCT关键字来保证查询结果不会返回重复元素

public void test() {
  String hql = "SELECT min(e.salary), max(e.salary) "
    + "FROM Employee e "
    + "GROUP BY e.dept "
    + "HAVING min(salary) > :minSal";
  
  Query query = session.createQuery(hql)
                 .setFloat("minSal", 800);
  
  List<Object []> result = query.list();
  for(Object [] objs: result){
   System.out.println(Arrays.asList(objs));
  }
 } 

HQL(迫切)左外连接

在mysql语句中左外连接和迫切左外连接是没有区别的,但是在hibernate框架中是有区别的。
含义:让左表和右表进行连接,左边的表必然出现,如果右边中没有满足条件的连接出现,左表数据仍然显示,只是连接的的数据为空。

迫切左外连接

1)LEFT JOINFETCH关键字表示迫切左外连接检索策略.
2)list()方法返回的集合中存放实体对象的引用,每个Department对象关联的Employee集合都被初始化,存放所有关联的Employee的实体对象.
3)查询结果中可能会包含重复元素,可以通过一个HashSet来过滤重复元素

public void test() {
  String hql="SELECT DISTINCT d From Department d LEFT JOIN FETCH d.emps";
  //DISTINCT用于去除重复的Department,如果不加返回的记录数为实际的sql查询的返回记录数
  //此处的DISTINCT会在sql语句中出现,但是实际上在SQL语句上面没有明显的用处
  //因为sql语句部门+机构不会照成重复的sql语句
  Query query=session.createQuery(hql);
  List<Department> depts=query.list();
  System.out.println(depts.size());
  for(Department dept:depts) {
   System.out.println(dept.getName()+"-"+dept.getEmps().size());
  }
 } 
public void test() {
  String hql="From Department d LEFT JOIN FETCH d.emps";
  Query query=session.createQuery(hql);
  List<Department> depts=query.list();
  depts=new ArrayList<>(new LinkedHashSet(depts));
  //是为了去除重复
  System.out.println(depts.size());
  for(Department dept:depts) {
   System.out.println(dept.getName()+"-"+dept.getEmps().size());
  }
 } 

左外连接

1)LEFT JOIN关键字表示左外连接查询.
2)list()方法返回的集合中存放的是对象数组类型
3)根据配置文件来决定Employee集合的检索策略.
4)如果希望list()方法返回的集合中仅包含Department对象,可以在HQL查询语句中使用SELECT关键字

public void test() {
  String hql="SELECT DISTINCT d From Department d LEFT JOIN d.emps";
  //DISTINCT去除重复,select d是为了强制使得返回为Department类型,此处默认返回为object
  Query query=session.createQuery(hql);
  List<Department> depts=query.list();
  System.out.println(depts.size());
  for(Department dept:depts)
  {
   System.out.println(dept.getName()+","+dept.getEmps().size());
   //element并没有完成初始化
  }
 } 

HQL(迫切)内连接

迫切内连接

1)INNER JOIN FETCH关键字表示迫切内连接,也可以省略INNER关键字
2)list()方法返回的集合中存放Department对象的引用,每个Department对象的Employee集合都被初始化,存放所有关联的Employee对象

内连接

1)INNER JOIN关键字表示内连接,也可以省略INNER关键字
2)list()方法的集合中存放的每个元素对应查询结果的一条记录,每个元素都是对象数组类型
3)如果希望list()方法的返回的集合仅包含Department对象,可以在HQL查询语句中使用SELECT关键字

关联级别运行时的检索策略

1)如果在HQL中没有显式指定检索策略,将使用映射文件配置的检索策略.
2)HQL会忽略映射文件中设置的迫切左外连接检索策略,如果希望HQL采用迫切左外连接策略,就必须在HQL查询语句中显式的指定它
3)若在HQL代码中显式指定了检索策略,就会覆盖映射文件中配置的检索策略

QBC 检索方式

使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口。
QBC查询就是通过使用Hibernate提供的QueryByCriteriaAPI来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口
1)测试示例

public void test() {
  Criteria criteria=session.createCriteria(Employee.class);
  criteria.add(Restrictions.eq("id",15));
  Employee employee=(Employee) criteria.uniqueResult();
  System.out.println(employee);
 } 

运行结果

Hibernate: 
    select
        this_.ID as ID1_1_0_,
        this_.NAME as NAME2_1_0_,
        this_.SALARY as SALARY3_1_0_,
        this_.EMAIL as EMAIL4_1_0_,
        this_.DEPT_ID as DEPT_ID5_1_0_ 
    from
        GG_EMPLOYEE this_ 
    where
        this_.ID=?
Employee [id=15]

测试代码2

public void test() {
  Criteria criteria=session.createCriteria(Employee.class);
  //and
  Conjunction conjunction=Restrictions.conjunction();
  conjunction.add(Restrictions.ilike("name", "a",MatchMode.ANYWHERE));
  Department dept=new Department();
  dept.setId(80);
  conjunction.add(Restrictions.eq("dept",dept));
  System.out.println(conjunction);
  //or
  Disjunction disjunction=Restrictions.disjunction();
  disjunction.add(Restrictions.ge("salary",6000f));
  disjunction.add(Restrictions.isNull("email"));
  
  criteria.add(disjunction);
  criteria.add(conjunction);
  
  criteria.list();
 } 

测试结果

Hibernate: 
    select
        this_.ID as ID1_1_0_,
        this_.NAME as NAME2_1_0_,
        this_.SALARY as SALARY3_1_0_,
        this_.EMAIL as EMAIL4_1_0_,
        this_.DEPT_ID as DEPT_ID5_1_0_ 
    from
        GG_EMPLOYEE this_ 
    where
        (
            this_.SALARY>=? 
            or this_.EMAIL is null
        ) 
        and (
            lower(this_.NAME) like ? 
            and this_.DEPT_ID=?
        )

测试代码

public void test() {
  Criteria criteria=session.createCriteria(Employee.class);
  criteria.setProjection(Projections.max("salary"));
  System.out.println(criteria.uniqueResult());
 } 

测试结果

Hibernate: 
    select
        max(this_.SALARY) as y0_ 
    from
        GG_EMPLOYEE this_
12000.0

测试代码:

public void test() {
  Criteria criteria=session.createCriteria(Employee.class);
  criteria.addOrder(Order.asc("salary"));
  criteria.addOrder(Order.desc("email"));
  int pageSize=5;
  int pageNo=3;
  criteria.setFirstResult((pageNo-1)*pageSize)
    .setMaxResults(pageSize)
    .list();
 } 

测试结果:

Hibernate: 
    select
        this_.ID as ID1_1_0_,
        this_.NAME as NAME2_1_0_,
        this_.SALARY as SALARY3_1_0_,
        this_.EMAIL as EMAIL4_1_0_,
        this_.DEPT_ID as DEPT_ID5_1_0_ 
    from
        GG_EMPLOYEE this_ 
    order by
        this_.SALARY asc,
        this_.EMAIL desc limit ?,
        ?

本地SQL检索方式

本地SQL查询来完善HQL不能涵盖所有的查询特性

public void test() {
  String sql="Insert into gg_department values(:value1,:value2)";
  Query query=session.createSQLQuery(sql);
  query.setParameter("value1", 280)
   .setParameter("value2", "ATGUIGU").executeUpdate();
 } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值