一、查询方式
1.Hibernate提供了以下几种检索对象的方式
¨ 导航对象图检索方式: 根据已经加载的对象导航到其他对象
¨ OID 检索方式: 按照对象的 OID 来检索对象
¨ HQL 检索方式: 使用面向对象的 HQL 查询语言
¨ QBC 检索方式: 使用 QBC(Query By Criteria) API 来检索对象. 这种 API 封装了基于字符串形式的查询语句, 提供了更加面向对象的查询接口.
¨ 本地 SQL 检索方式: 使用本地数据库的 SQL 查询语句
2.性能比较
比较方面 | HQL检索 | QBC检索 |
可读性 | 优点:和sql相近,易读 | 将语句肢解成一组criteria,较差 |
功能 | 支持各种查询 | 不支持报表查询和子查询。有限的连接查询 |
查询语句形式 | 基于字符串形式的sql | 更加面向对象 |
何时被解析 | 运行时被解析 | 编译时被解析,更易排错 |
可扩展性 | 不具扩展性 | 用户可扩展criteria接口 |
对动态查询语句的支持 | 支持动态查询,编程麻烦 | 适合动态生成查询语句 |
这么多,反正常用就是hql/qbc
二、HQL
1.功能
¨ 在查询语句中设定各种查询条件
¨ 支持投影查询, 即仅检索出对象的部分属性
¨ 支持分页查询
¨ 支持连接查询
¨ 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
¨ 提供内置聚集函数, 如 sum(), min()和 max()
¨ 能够调用 用户定义的 SQL 函数或标准的 SQL 函数
¨ 支持子查询
¨ 支持动态绑定参数
发现了吗!很类似与sql语句。连分组查询,聚合函数,子查询等都和sql类似。功能与sql类似。
2.基本结构
¨ 1. 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数
¨ 2. 动态绑定参数
¨ 3.调用 Query 的 list() 方法执行查询语句. 该方法返回java.util.List 类型的查询结果, 在 List 集合中存放了符合查询条件的持久化对象.
Qurey 接口支持方法链编程风格, 它的 setXxx() 方法返回自身实例, 而不是 void 类型
代码:
/**
* 通过name来查询user
* 主要目的是,学习query及hql语句
* @param name
* @return
*/
public User query(String name)
{
//注意:不是使用sql语句,而是hql语句(一种hibernate自定义的似sql语句)
//如何学呢?
Session session = null ;
try {
session = HibernateUtil.getSession();
//String hql = "from User as user where user.name=?";//必须的as一下否则会出错
String hql = "from User as user where user.name=:name";//注意,中英文标点
//1. 通过 Session 的 createQuery() 方法创建一个 Query 对象, 它包括一个 HQL 查询语句. HQL 查询语句中可以包含命名参数
Query query = session.createQuery(hql);
// 2. 动态绑定参数(两种方式)
//query.setString(0, name);//注意是从0开始
query.setString("name", name);
//分页
query.setFirstResult(0);
query.setMaxResults(2);
//3.调用 Query 的 list() 方法执行查询语句. 该方法返回java.util.List 类型的查询结果,
//在 List 集合中存放了符合查询条件的持久化对象.
List<User> list = query.list();
for(User user: list)
{
System.out.println(user.getName()+"id" + user.getId());
//new User()
}
} finally{
if(session != null)
{
session.close();
}
}
return null;
}
2.其它一些功能
子查询:
类似
from Customer c where 1 < (select count(o) from c.orders o);
其它的查询方式就不介绍了。
三、事务
1.不设置隔离会发生什么情况
• 脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
• 不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
• 幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
2.数据库的隔离级别
SQL ANSI SQL 标准定义了 4 种事务隔离级别,级别越高,成本越高:
2.在数据库中如何设置隔离级别(以mysql为例)
不同的数据库支持隔离级别不同。
¨ 每启动一个 mysql 程序, 就会获得一个单独的数据库连接. 每个数据库连接都有一个全局变量 @@tx_isolation, 表示当前的事务隔离级别. MySQL 默认的隔离级别为 Repeatable Read
¨ 查看当前的隔离级别:
• 当前连接:SELECT@@tx_isolation;
• 全局:SELECT @@global.tx_isolation;
¨ 设置当前 mySQL 连接的隔离级别:
• set transaction isolation levelread committed;
• 或set session transaction isolation level read uncommitted;
¨ 设置数据库系统的全局的隔离级别:
• set global transactionisolation level read committed;
3.在hibernate中如何设置隔离级别
在 Hibernate 的配置文件中可以显式的设置隔离级别. 每一个隔离级别都对应一个整数:
隔离级别 | 对应的整数表示 |
READ UNCOMMITED | 1 |
READ COMMITED | 2 |
REPEATABLE READ | 4 |
SERIALIZEABLE | 8 |
Hibernate 通过为 Hibernate 映射文件指定 hibernate.connection.isolation 属性来设置事务的隔离级别。例:
hibernate.connection.isolation = 4
注意
¨ Hibernate不可能改变在受管环境下由应用服务器提供的数据库连接的隔离级别,只能通过改变应用服务器配置的方式来改变.
¨ 设置隔离级别是全局选项,会影响所有的连接和事务