Hibernate_day03总结
今日内容
l Hibernate的检索方式
l Hibernate的抓取策略
l Hibernate的批量检索
l 事务的并发问题
1.1 上次课内容回顾:
Hibernate的持久类三种状态:
* 瞬时态:没有唯一标识OID,没有被session管理
* 持久态:有唯一标识OID,被session管理
* 脱管态:有唯一标识OID,没有被session管理.
* 状态转换:
瞬时态:new 获得.
* 瞬时à持久:save/saveOrUpdate
* 瞬时à脱管:user.setId(1);
持久态:get/load/find
* 持久à脱管:close,clear,evict
* 持久à瞬时:delete
脱管态:new User() user.setId(1);
* 脱管à持久:update,saveOrUpdate
* 脱管à瞬时:user.setId(null);
Hibernate的一级缓存:
* Hibernate一级缓存:session级别缓存.
* session中一系列的Java集合.
* session中一级缓存存在:
* 快照区:
* 一级缓存常用操作的方法:
* clear/flush/evict/refresh
Hibernate的操作持久化类的常用的方法:
* save/update/get/load/delete/saveOrUpdate
Hibernate的关联关系映射:
* 一对多:
* 部门和员工:
* 部门实体:
* Set<Employee> employees = new HashSet<Employee>();
* 员工实体:
* Department department
* 部门映射:
<set name=”employees”>
<key column=”dno”/>
<one-to-many class=”..Employee”/>
</set>
* 员工映射:
<many-to-one name=”department” class=”Department” column=”dno”/>
* cascade:级联 控制的是关联的对象.
* inverse:外键维护 控制的是外键的关系.
* 多对多:
* 一对一:
1.2 Hibernate的检索方式:
1.2.1 Hibernate的检索方式:
Hibernate中提供了五种检索方式:
1.对象导航检索:
* Customer customer = session.get(Customer.class,1);
* customer.getOrders();
* Order order = session.get(Order.class,1);
* order.getCustomer().getCname();
2.OID检索:
* session.get(Customer.class,1);
* session.load(Customer.class,1);
3.HQL检索:
HQL:Hibernate Query Language.
Query query = session.createQuery(String hql);
4.QBC检索:
QBC:Query By Criteria
Criteria criteria = session.createCriteria(Class clazz);
5.SQL检索:
SQL:
SQLQuery query = session.createSQLQuery(String sql);
1.2.2 HQL检索:
HQL概述:
HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:
在查询语句中设定各种查询条件
支持投影查询, 即仅检索出对象的部分属性
支持分页查询
支持连接查询
支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
提供内置聚集函数, 如 sum(), min() 和 max()
能够调用 用户定义的 SQL 函数或标准的 SQL 函数中
支持子查询
支持动态绑定参数
HQL的简单查询:
@Test
/**
* 简单查询:查询所有记录
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/*Query query = session.createQuery("from Customer");
List<Customer> list = query.list();*/
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
HQL的别名查询:
@Test
/**
* 别名查询:
* * 使用as 定义别名 (as可以省略)
*/
publicvoid demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// HQL中不支持select * 写法.
// List<Customer> list = session.createQuery("from Customer as c").list();
// List<Customer> list = session.createQuery("from Customer c").list();
List<Customer> list = session.createQuery("select c from Customer c").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
HQL的多态查询(了解)
@Test
/**
* 多态查询
*/
publicvoid demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 查询所有继承了Object的持久化类.
Listlist = session.createQuery("from java.lang.Object").list();
System.out.println(list);
tx.commit();
session.close();
}
HQL的排序查询:
@Test
/**
* 排序查询
*/
publicvoiddemo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// List<Customer> list = session.createQuery("from Customer order by age asc").list();
List<Customer> list = session.createQuery("from Customer order by age desc").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
HQL的分页查询:
@Test
/**
* 分页查询
*/
publicvoid demo6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("from Order");
// 设置从哪开始:
query.setFirstResult(10);
query.setMaxResults(10);
List<Order> list = query.list();
for (Order order : list) {
System.out.println(order);
}
tx.commit();
session.close();
}
HQL的检索单个对象:
@Test
/**
* 检索单个对象
*/
publicvoid demo7(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.createQuery("from Customer where cname = ?").setString(0, "老马").uniqueResult();
System.out.println(customer);
tx.commit();
session.close();
}
HQL的条件查询:
@Test
/**
* 条件对象
*/
publicvoid demo8(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/**
* 按位置绑定参数
*/
/*Query query = session.createQuery("from Customer where cname like ? and age > ?");
query.setParameter(0, "%马%");
query.setParameter(1, 38);*/
/**
* 按名称进行绑定参数
*/
Query query = session.createQuery("from Customer where cname like :cname and age > :age");
query.setParameter("cname", "%马%");
query.setParameter("age", 38);
List<Customer> list= query.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
HQL的投影查询:
@Test
/**
* 投影查询
*/
publicvoid demo9(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 查询cname这列的值
/*List<String> list = session.createQuery("select cname from Customer").list();
for (String string : list) {
System.out.println(string);
}*/
// 查询cname,age这两个列的值:
/*List<Object[]> list = session.createQuery("select cname,age from Customer").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}*/
// 使用构造查询:
List<Customer> list = session.createQuery("select new Customer(cname,age) from Customer").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
HQL的聚合查询
@Test
/**
* 聚合函数查询
*/
publicvoid demo10(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/*Long count = (Long) session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(count);*/
Integer age = (Integer) session.createQuery("select max(age) from Customer").uniqueResult();
System.out.println(age);
tx.commit();
session.close();
}
HQL的分组查询:
@Test
/**
* 分组查询
*/
publicvoid demo11(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Object[]> list = session.createQuery("select o.customer.cname,count(*) from Order o group by o.customer.cname").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
tx.commit();
session.close();
}
1.2.3 QBC检索:
QBC检索的概述:
QBC:Query By Criteria:条件查询.专门用来进行条件查询.更加面向对象.
QBC简单查询:
@Test
/**
* 简单查询:
*/
publicvoid demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createCriteria(Customer.class).list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
QBC排序查询:
@Test
/**
* 排序查询:
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.asc("age"));
criteria.addOrder(Order.desc("age"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
QBC的分页查询:
@Test
/**
* 分页查询:
*/
publicvoiddemo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Order.class);
criteria.setFirstResult(10);
criteria.setMaxResults(10);
List<Order> list = criteria.list();
for (Order order : list) {
System.out.println(order);
}
tx.commit();
session.close();
}
QBC条件查询:
@Test
/**
* 条件查询:
*/
publicvoiddemo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Criteria criteria = session.createCriteria(Customer.class);
// 设置条件:
/*criteria.add(Restrictions.like("cname", "%马%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}*/
criteria.add(Restrictions.like("cname", "%马%"));
criteria.add(Restrictions.gt("age", 38));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
1.2.4 连接查询:
SQL中连接查询
连接查询:多表查询.
SQL中有哪些连接的方式?
* 交叉连接:
* select * from A,B; --- 得到的结果两个表的笛卡尔积.
* 内连接:inner join (inner可以省略)
* 隐式内连接:
* select * from A ,B where 条件;
* 显示内连接:
* select * from A inner join B on 条件;
* 外连接:outer join (outer 可以省略)
* 左外连接:
* select * from A left outer join B on 条件;
* 右外连接:
* select * from A right outer join B on 条件;
面试题:内连接和外连接有什么区别?
Hibernate中的连接查询(HQL连接查询)
HQL连接查询的时候:
* 交叉连接:
* 内连接:
* 显示内连接:inner join
* 隐式内连接:where
* 迫切内连接:
* 外连接:
* 左外连接:
* 右外连接:
* 迫切左外连接:
@Test
/**
* 区分内连接和迫切内连接区别
*/
publicvoid demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/**
* 内连接的SQL:
* SELECT * FROM customer c INNER JOIN orders o ON c.cid = o.cno;
* SELECT * FROM customer c,orders o WHERE c.cid = o.cno;
*/
/*List<Object[]> list = session.createQuery("from Customer c inner join c.orders").list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}*/
/**
* 迫切内连接:语法.inner join fetch
* ***** 迫切内连接和 内连接生成的SQL语句是一样的!!!
*/
List<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.orders").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
1.2.5 命名查询:
可以在配置文件中配置一个HQL,给HQL取个名字.通过名称获得到执行的HQL.
在映射文件中预定义一个HQL/SQL
<query name=”findAllCustomer”>from Customer</query>
@Test
/**
* 命名查询:
*/
publicvoiddemo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.getNamedQuery("findAllCustomer").list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
1.2.6 离线条件查询:
DetachedCriteria:离线条件查询.可以在没有session的情况下使用,在DAO层再去绑定session.应用在条件查询上.
Criteria:必须使用session创建.Criteria必须在DAO层才能使用.
@Test
/**
* 离线条件查询
*/
publicvoid demo3(){
DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
detachedCriteria.add(Restrictions.like("cname", "%马%"));
detachedCriteria.add(Restrictions.gt("age", 38));
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Customer> list = detachedCriteria.getExecutableCriteria(session).list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
session.close();
}
1.3 Hibernate的抓取策略:
1.3.1 延迟加载:是否在执行语句的时候马上查询该对象.
类级别延迟加载:
Customer customer = session.load(Customer.class,1);
以下办法使延迟加载失效
持久化类如果使用final进行修饰,那么延迟加载就会失效!!!
<class>标签上有一个属性:lazy=”true”.配置lazy=”false”使类级别延迟加载失效.
Hibernate.initalize(Object proxy);
关联级别的延迟:
在<many-to-one>,<set>,<one-to-one>上lazy属性.
1.3.2 抓取策略:查询一个对象的时候,是否查询其关联对象.
<set>集合上的fetch和lazy
fetch:控制查询其关联对象采用的SQL语句的格式.
* select :普通select查询.(默认)
* join :使用连接查询.(fetch配置为join那么lazy就会失效.)
* subselect :使用子查询查询其关联对象.
lazy:控制查询其关联对象是否采用延迟加载
* true :采用延迟加载(默认)
* false :不采用延迟加载.立即加载
* extra :及其懒惰.
测试代码:详见HibernateDemo5.
<many-to-one>上的fetch 和 lazy:
fetch:控制SQL的格式
* select :普通select语句(默认)
* join :迫切左外连接
lazy:控制关联对象是否采用延迟
* false :不采用延迟加载
* proxy :默认.当前对象是否采用延迟,由另一方的<class>上的lazy属性来决定.
* no-proxy :
代码详见 HibernateDemo6
批量抓取:
查询客户时候批量抓取订单:
@SuppressWarnings("unchecked")
@Test
/**
* 查询客户,批量抓取订单
* <set>上配置batch-size=""
*/
publicvoid demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Customer> list = session.createQuery("from Customer").list();
for (Customer customer : list) {
System.out.println(customer);
System.out.println(customer.getOrders().size());
}
tx.commit();
session.close();
}
查询订单的时候,批量查询客户.
@SuppressWarnings("unchecked")
@Test
/**
* 查询订单,批量抓取客户
* 在.hbm.xmlCustomer中<class>上配置batch-size
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
List<Order> list = session.createQuery("from Order").list();
for (Order order : list) {
System.out.println(order);
System.out.println(order.getCustomer().getCname());
}
tx.commit();
session.close();
}
1.4 Hibernate的事务管理:
1.4.1 回顾事务:
什么是事务:
事务:指的是逻辑上一组操作,各个单元要么一起成功,要么一起失败!
事务特点:
原子性:指的是事务不可分割.
一致性:事务执行的前后,数据的完整性保持一致.
隔离性:一个事务在执行的过程中,不应该受到其他事务的干扰.
持久性:一个事务一旦执行结束,那么数据就永久的保存到数据库中.
如果不考虑事务的隔离性,引发哪些问题:
两大类问题:
* 读问题:
* 脏读 :一个事务读到了另一个事务还没有提交的数据.
* 不可重复读 :一个事务读到了另一个事务已经提交的update数据,而导致多次查询结果不一致.
* 虚读 :一个事务读到了另一个事务已经提交的insert数据,而导致多次查询结果不一致.
* 写问题:
* 引发两类丢失更新问题:
避免以上问题的发生:
避免读问题:
* 设置事务的隔离级别:
* 未提交读:以上读情况都能发生.
* 已提交读:避免脏读.但是不可重复读和虚读有可能发生.
* 可重复读:避免脏读,不可重复读.但是虚读有可能发生.
* 串行化 :避免以上所有读的问题.
避免写问题:
* 悲观锁:
* 乐观锁:
1.4.2 Hibernate中避免读问题:
设置事务的隔离级别:
<property name="hibernate.connection.isolation">4</property>
1.4.3 Hibernate避免写问题:
悲观锁:
@SuppressWarnings("deprecation")
@Test
/**
* 使用悲观锁解决丢失更新
*/
publicvoid demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1, LockMode.UPGRADE);
customer.setCname("小马");
tx.commit();
session.close();
}
@SuppressWarnings("deprecation")
@Test
/**
* 使用悲观锁解决丢失更新
*/
publicvoid demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1, LockMode.UPGRADE);
customer.setAge(52);
tx.commit();
session.close();
}
乐观锁:
@Test
/**
* 使用乐观锁解决丢失更新
*/
publicvoid demo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1);
customer.setCname("小马");
tx.commit();
session.close();
}
@Test
/**
* 使用乐观锁解决丢失更新
*/
publicvoid demo6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 1);
customer.setAge(52);
tx.commit();
session.close();
}
1.4.4 线程绑定的session的使用:
配置:
<!-- 开启与线程绑定的session -->
<propertyname="hibernate.current_session_context_class">thread</property>
使用sessionFactory.getCurrentSession();
1.5 Hibernate的反向工程:
1.5.1 Hibernate反向工程:
步骤一:创建一个数据库视图:
步骤二:新建工程:
步骤三:反向工程.回到数据库视图:
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有