hibernate检索方式(HQL 检索方式,QBC 检索方式,本地 SQL 检索方式)
hibernate有五种检索方式,这儿用 单向的一对多的映射关系 例子,这儿有后三种的方式;
导航对象图检索方式: 根据已经加载的对象导航到其他对象
OID 检索方式: 按照对象的 OID 来检索对象
HQL 检索方式: 使用面向对象的 HQL 查询语言
QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口.
本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句
建立封装数据库中数据属性的封装类:n-1;
n的一端封装类:
package com.atguigu.hibernate.entities; import java.util.HashSet; import java.util.Set; public class Department { private Integer id; private String name; private Set<Employee> emps=new HashSet<>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Employee> getEmps() { return emps; } public void setEmps(Set<Employee> emps) { this.emps = emps; } @Override public String toString() { return "Department [id=" + id + "]"; } }
1的一端封装的类:
package com.atguigu.hibernate.entities; public class Employee { private Integer id; private String name; private float salary; private String email; private Department dept; public Employee() { super(); } public Employee(String name, float salary, String email, Department dept) { super(); this.name = name; this.salary = salary; this.email = email; this.dept = dept; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getSalary() { return salary; } public void setSalary(float salary) { this.salary = salary; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } @Override public String toString() { return "Employee [id=" + id + "]"; } }
在该包下自动生成对用的关系映射文件,只需进行一些修改;
单向的n-1映射关联关系,1的一端,关系映射文件;
<?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 2016-9-26 8:08:56 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.atguigu.hibernate.entities"> <class name="Employee" table="LL_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="Department"> <column name="DEPT_id" /> </many-to-one> </class> <!-- 在映射文件中定义命名查询语句 ,书写的位置不在class范围内,注意书写的位置--> <query name="salaryemp"><![CDATA[from Employee e where e.salary >:minSal and e.salary <:maxSal]]></query> </hibernate-mapping>
单向的n-1映射关联关系,n的一端,关系映射文件;
<?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 2016-9-26 8:08:56 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping package="com.atguigu.hibernate.entities"> <class name="Department" table="LL_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="LL_EMPLOYEE" inverse="true" lazy="true"> <key> <column name="DEPT_ID" /> </key> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>
在src目录下建立hibernate的配置文件:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Hibernate 连接数据库的基本信息 --> <property name="connection.username">lxn123</property> <property name="connection.password">lxn123</property> <property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl1</property> <!-- --> <!-- Hibernate 的基本配置 --> <!-- Hibernate 使用的数据库方言 ,是oracle书籍库的基本方言--> <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property> <!-- 运行时是否打印 SQL --> <property name="show_sql">true</property> <!-- 运行时是否格式化 SQL --> <property name="format_sql">true</property> <!-- 生成数据表的策略 --> <property name="hbm2ddl.auto">update</property> <!-- 设置 Hibernate 的事务隔离级别 --> <property name="connection.isolation">2</property> <!-- 删除对象后, 使其 OID 置为 null --> <property name="use_identifier_rollback">true</property> <!-- 配置 C3P0 数据源,不是开发 这儿就不配置了 --> <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 --> <property name="hibernate.jdbc.fetch_size">100</property> <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 --> <property name="jdbc.batch_size">30</property> <!-- 需要关联的 hibernate 映射文件 .hbm.xml --> <mapping resource="com/atguigu/hibernate/entities/Department.hbm.xml"/> <mapping resource="com/atguigu/hibernate/entities/Employee.hbm.xml"/> </session-factory> </hibernate-configuration>
建立测试类,进行测试方法;
package com.atguigu.hibernate.test; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.criterion.Conjunction; import org.hibernate.criterion.Disjunction; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Order; import org.hibernate.criterion.Projections; import org.hibernate.criterion.Restrictions; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; import com.atguigu.hibernate.entities.Department; import com.atguigu.hibernate.entities.Employee; public class HqlTest { private static SessionFactory sessionFactory; private static Session session; private static Transaction transaction; @Before public void init(){ Configuration configuration=new Configuration().configure(); ServiceRegistry serviceRegistry= new ServiceRegistryBuilder() .applySettings(configuration.getProperties()) .buildServiceRegistry(); sessionFactory=configuration.buildSessionFactory(serviceRegistry); session=sessionFactory.openSession(); transaction=session.beginTransaction(); } @After public void destroy(){ transaction.commit(); session.close(); sessionFactory.close(); } @Test //hql也可以进行曾删改的操作 public void testHQLUpdate(){ String hql = "DELETE FROM Department d WHERE d.id = :id"; session.createQuery(hql).setInteger("id", 280) .executeUpdate(); } @Test //本地 SQL 检索 public void testNativeSQL(){ String sql = "INSERT INTO ll_department VALUES(?, ?)"; Query query = session.createSQLQuery(sql); query.setInteger(0, 280) .setString(1, "ATGUIGU") .executeUpdate(); } @Test //QBC检索, 添加排序,添加翻页方法 public void testQBC4(){ Criteria criteria = session.createCriteria(Employee.class); //1. 添加排序 criteria.addOrder(Order.asc("salary")); criteria.addOrder(Order.desc("email")); List<Employee> empss=criteria.list(); System.out.println(empss); //2. 添加翻页方法 int pageSize = 5; int pageNo = 3; List<Employee> emps=criteria.setFirstResult((pageNo - 1) * pageSize) .setMaxResults(pageSize) .list(); System.out.println(emps); } @Test //QBC检索,统计查询 public void testQBC3(){ Criteria criteria = session.createCriteria(Employee.class); //统计查询: 使用 Projection 来表示: 可以由 Projections 的静态方法得到 criteria.setProjection(Projections.max("salary")); System.out.println(criteria.uniqueResult()); } @Test //QBC检索,AND OR public void testQBC2(){ Criteria criteria = session.createCriteria(Employee.class); //1. AND: 使用 Conjunction 表示 //Conjunction 本身就是一个 Criterion 对象 //且其中还可以添加 Criterion 对象 Conjunction conjunction = Restrictions.conjunction(); conjunction.add(Restrictions.like("name", "a", MatchMode.ANYWHERE)); Department dept = new Department(); dept.setId(80); conjunction.add(Restrictions.eq("dept", dept)); System.out.println(conjunction); //2. OR Disjunction disjunction = Restrictions.disjunction(); disjunction.add(Restrictions.ge("salary", 6000F)); disjunction.add(Restrictions.isNull("email")); criteria.add(disjunction); criteria.add(conjunction); criteria.list(); System.out.println(criteria); } @Test //QBC检索 public void testQBC(){ //1. 创建一个 Criteria 对象 Criteria criteria = session.createCriteria(Employee.class); //2. 添加查询条件: 在 QBC 中查询条件使用 Criterion 来表示 //Criterion 可以通过 Restrictions 的静态方法得到 //eq,是等于,gt是大于 criteria.add(Restrictions.eq("email", "SKUMAR")); criteria.add(Restrictions.gt("salary", 5000F)); //3. 执行查询 Employee employee = (Employee) criteria.uniqueResult(); System.out.println(employee); } @Test //内连接 public void testinnerjoin(){ String hql = "SELECT e FROM Employee e INNER JOIN e.dept"; Query query = session.createQuery(hql); List<Employee> emps = query.list(); emps=new ArrayList<>(new LinkedHashSet<>(emps)); System.out.println(emps.size()); for(Employee emp: emps){ System.out.println(emp.getName() + ", " + emp.getDept().getName()); } } @Test //迫切内连接 public void testinnerjoinfetch(){ String hql = "FROM Department d INNER 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()); } } @Test //左外连接,DISTINCT取消重复的行 public void testLeftJoin(){ String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps"; 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()); } // List<Object []> result = query.list(); // result = new ArrayList<>(new LinkedHashSet<>(result));,取消重复的行 // System.out.println(result); // // for(Object [] objs: result){ // System.out.println(Arrays.asList(objs)); // } } //迫切左外连接LEFT JOIN FETCH,DISTINCT是取消重复的行 public void testLeftJoinFetch(){ String hql="select distinct d from Department d left join fetch d.emps"; Query query=session.createQuery(hql); List<Department> depts=query.list(); //取消重复的行,set集合中没有重复的值 depts=new ArrayList<>(new LinkedHashSet<>(depts)); System.out.println(depts.size()); for(Department dept:depts){ System.out.println(dept.getName()+"--"+dept.getEmps()); } } //报表查询,即在sql是分组查询,只查询部分属性 public void testGroupBy(){ String hql="select min(e.salary),max(e.salary) " + "from Employee e group by e.dept having min(salary)>:de"; Query query=session.createQuery(hql).setFloat("de", 5000); //数组的形式 List<Object []> result=query.list(); for(Object [] emp:result){ System.out.println(Arrays.asList(emp)); } } //投影查询,即查询部分属性 public void testFieldQuery2(){ String hql="select new Employee(e.name,e.salary,e.email,e.dept) " + "from Employee e where e.dept=:dept"; Query query=session.createQuery(hql); Department dept=new Department(); dept.setId(80); //封装类形式的 List<Employee> result=query.setEntity("dept", dept).list(); for(Employee emp:result){ System.out.println(emp.getName()+","+emp.getSalary()+","+emp.getEmail()+","+emp.getDept()); } } @Test //投影查询,即查询部分属性 public void testFieldQuery(){ String hql="select e.email,e.salary,e.dept 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 [] emps:result){ System.out.println(Arrays.asList(emps)); } } //在映射文件中定义命名查询语句方式的命名查询,在映射文件中要配置的。。。 //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值 public void testNamedQuery(){ Query query =session.getNamedQuery("salaryemp"); List<Employee> emps= query.setFloat("minSal", 5000) .setFloat("maxSal", 10000) .list(); System.out.println(emps.size()); } //分页查询,此查询只能查询到,对应的id @Test public void testPageQuery(){ String hql="from Employee"; Query query=session.createQuery(hql); //第三页 int pageNo=3; //每页的大小为5 int pageSize=5; /* * setFirstResult(int firstResult): 设定从哪一个对象开始检索, * 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. * 默认情况下, Query 从查询结果中的第一个对象开始检索 * * setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. * 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象 * */ List<Employee> emps= query.setFirstResult((pageNo-1)*pageSize) .setMaxResults(pageSize).list(); System.out.println(emps); } //基于命名参数的查询 //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值 public void testHQLNamedParameter(){ //1. 创建 Query 对象 //基于命名参数. String hql="from Employee e where e.salary > :sal and e.email like :ema"; Query query = session.createQuery(hql); //2. 绑定参数。setFloat,setString,都为设置属性的类型 query.setFloat("sal", 7000).setString("ema", "%A%"); //3. 执行查询 List<Employee> emp=query.list(); System.out.println(emp.size()); } //此查询方法,只能查询到在此范围内的个数,不能查询到具体的属性值 public void testHql(){ //1. 创建 Query 对象 //基于位置的参数.hql是面向对象的,所以,书写表名时 为封装属性的类名; String hql="FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ? " + "ORDER BY e.salary"; Query query=session.createQuery(hql); //2. 绑定参数 //Query 对象调用 setXxx 方法支持方法链的编程风格. Department dept=new Department(); dept.setId(80); query.setFloat(0, 5000).setString(1, "%A%").setEntity(2, dept); //3. 执行查询 List<Employee> emp=query.list(); System.out.println(emp.size()); } }