- 总配置文件:hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
<!-- 配置连接数据库的基本信息 -->
<property name="connection.username">scott</property>
<property name="connection.password">scott</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
<!-- 配置hibernat的基本信息 -->
<!-- hibernate 所使用的数据库方言 -->
<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>
<!-- 删除对象对应的数据后,使这个对象的OID为null -->
<property name="use_identifier_rollback">true</property>
<!-- 如果控制台重复建表,并且提示重复名或者外键名什么的,就把这行添加上,值为用户名即可 -->
<property name="default_schema">scott</property>
<!-- 配置c3p0数据库连接池 -->
<!--
<property name="c3p0.max_size">10</property>
<property name="c3p0.min_size">5</property>
<property name="c3p0.acquire_increment">2</property>
<property name="c3p0.idle_test_period">2000</property>
<property name="c3p0.timeout">2000</property>
<property name="c3p0.max_statements">10</property>
-->
<!-- 引入对象关系映射文件 -->
<mapping resource="com/zc/cris/test/enties/Department.hbm.xml" />
<mapping resource="com/zc/cris/test/enties/Employee.hbm.xml" />
</session-factory>
</hibernate-configuration>
hibernate的检索方式概述
Hibernate 提供了以下几种检索对象的方式
导航对象图检索方式: 根据已经加载的对象导航到其他对象(getter方法)
OID 检索方式: 按照对象的 OID 来检索对象( get(Class clazz, int primaryKey))
- HQL 检索方式: 使用面向对象的 HQL 查询语言
- QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口.
- 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句
hql检索方式的优点:
HQL 检索方式包括以下步骤:
通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数
动态绑定参数
调用 Query 相关方法执行查询语句.
Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型
HQL vs SQL:
HQL 查询语句是面向对象的, Hibernate 负责解析 HQL 查询语句, 然后根据对象-关系映射文件中的映射信息, 把 HQL 查询语句翻译成相应的 SQL 语句. HQL 查询语句中的主体是域模型中的类及类的属性
SQL 查询语句是与关系数据库绑定在一起的. SQL 查询语句中的主体是数据库表及表的字段.
代码:
/*
* 第一个hql查询语句
*/
@Test
void testHQL() {
//1. 创建 query 对象的两种方式
//1.1 基于占位符设置查询参数(支持代码链)
// String hql = "from Employee e where e.salary >?0 and e.email like ?1";
// Query query = this.session.createQuery(hql).setParameter("0", 1200F).setParameter("1", "%qq%");
//1.2 基于命名参数设置查询参数(支持代码链)
String hql = "from Employee e where e.salary > :sal and e.email like :email"
+ " and e.department = :dept"
+ " order by e.salary";
Department dept = new Department();
dept.setId(20);
//2. 绑定参数
Query query = this.session.createQuery(hql)
.setParameter("sal", 1200F).
setParameter("email", "%qq%")
.setParameter("dept", dept); //参数类型还可以是实体类型
//3. 执行查询
List<Employee> list = query.list();
System.out.println(list.size());
}
- console:
hibernate实现分页
setFirstResult(int firstResult): 设定从哪一个对象开始检索, 参数 firstResult 表示这个对象在查询结果中的索引位置, 索引位置的起始值为 0. 默认情况下, Query 从查询结果中的第一个对象开始检索
setMaxResults(int maxResults): 设定一次最多检索出的对象的数目. 在默认情况下, Query 和 Criteria 接口检索出查询结果中所有的对象
代码:
/*
* 分页查询
*/
@Test
void testPageQuery() {
String hql = "from Employee";
Query query = this.session.createQuery(hql);
int pageNo = 2;
int pageSize = 2;
//hibernate特殊的分页公式(不需要关心底层数据库是mysql还是oracle)
List<Employee> list = query.setFirstResult((pageNo - 1) * pageSize).setMaxResults(pageSize).list();
System.out.println(list.get(0).getName());
}
- console:
命名查询
Hibernate 允许在映射文件中定义字符串形式的查询语句.
元素用于定义一个 HQL 查询语句, 它和 元素并列.在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象.
- 代码:
<query name="empsBySalary"><![CDATA[from Employee e where e.salary > :minSalary and e.salary < :maxSalary]]></query>
/*
* 命名查询
*/
@Test
void testNamedQuery() {
//命名查询:将hql语句设置到对应的映射文件中的query节点
Query query = this.session.getNamedQuery("empsBySalary");
List list = query.setParameter("minSalary", 1000F).setParameter("maxSalary", 1300F).list();
System.out.println(list.size());
}
投影查询
- 投影查询: 查询结果仅包含实体的部分属性. 通过 SELECT 关键字实现.
Query 的 list() 方法返回的集合中包含的是数组类型的元素, 每个对象数组代表查询结果的一条记录
可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录, 使程序代码能完全运用面向对象的语义来访问查询结果集.
- 可以通过 DISTINCT 关键字来保证查询结果不会返回重复元素
- 代码:
/*
* 投影查询(默认返回Object数组的list)
*/
@Test
void testFieldQuery() {
String hql = "select e.email, e.name, e.id from Employee e where e.department = :dept";
Department dept = new Department();
dept.setId(20);
List<Object[]> list = this.session.createQuery(hql).setParameter("dept", dept).list();
for(Object[] objs : list) {
System.out.println(Arrays.asList(objs));
}
}
- console:
- 改良版投影映射
/*
* 升级版投影查询
*/
@Test
void testFieldQuery2() {
//Employee必须要有对应的带参构造器(形参顺序必须一一对应)
String hql = "select new Employee(e.id, e.name, e.email, e.department) "
+ "from Employee e "
+ "where e.department = :dept";
Department dept = new Department();
dept.setId(20);
List<Employee> list = this.session.createQuery(hql).setParameter("dept", dept).list();
for(Employee emp : list) {
System.out.println(emp.getId()+"---"+emp.getName()+"----"+emp.getEmail()+"----"+emp.getDepartment());
}
}
- console:
报表查询
报表查询用于对数据分组和统计, 与 SQL 一样, HQL 利用 GROUP BY 关键字对数据分组, 用 HAVING 关键字对分组数据设定约束条件
在 HQL 查询语句中可以调用以下聚集函数
- count()
- min()
- max()
- sum()
- avg()
- 代码:
@Test
void testGroupBy() {
//查询员工最低工资大于1200的部门里的员工最高薪资和最低薪资
String hql = "select min(e.salary), max(e.salary) from Employee e "
+ "group by e.department "
+ "having min(e.salary) > :minSalary";
List<Object[]> list = this.session.createQuery(hql).setParameter("minSalary", 1200F).list();
for(Object[] objs: list) {
System.out.println(Arrays.asList(objs));
}
}
- console:
注意:如果连接oracle数据库发生重复建表或者外键的情况,请参考以下网页
http://bbs.youkuaiyun.com/topics/392051855