前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hibernate_day03总结

Hibernate_day03总结

作者头像
Java帮帮
发布2018-03-19 12:03:24
1K0
发布2018-03-19 12:03:24
举报

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的简单查询:

代码语言:javascript
复制
@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的别名查询:

代码语言:javascript
复制
@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的多态查询(了解)

代码语言:javascript
复制
@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的排序查询:

代码语言:javascript
复制
@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的分页查询:

代码语言:javascript
复制
@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的检索单个对象:

代码语言:javascript
复制
@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的条件查询:

代码语言:javascript
复制
@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的投影查询:

代码语言:javascript
复制
@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的聚合查询

代码语言:javascript
复制
@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的分组查询:

代码语言:javascript
复制
@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简单查询:

代码语言:javascript
复制
@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排序查询:

代码语言:javascript
复制
@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的分页查询:

代码语言:javascript
复制
@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条件查询:

代码语言:javascript
复制
@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

* 迫切内连接:

* 外连接:

* 左外连接:

* 右外连接:

* 迫切左外连接:

代码语言:javascript
复制
@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

代码语言:javascript
复制
<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层才能使用.

代码语言:javascript
复制
@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

批量抓取:

查询客户时候批量抓取订单:

代码语言:javascript
复制
@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();
}

查询订单的时候,批量查询客户.

代码语言:javascript
复制
@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中避免读问题:

设置事务的隔离级别:

代码语言:javascript
复制
<property name="hibernate.connection.isolation">4</property>

1.4.3 Hibernate避免写问题:

悲观锁:

代码语言:javascript
复制
@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();
}

乐观锁:

代码语言:javascript
复制
@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的使用:

配置:

代码语言:javascript
复制
<!-- 开启与线程绑定的session -->
<propertyname="hibernate.current_session_context_class">thread</property>

使用sessionFactory.getCurrentSession();

1.5 Hibernate的反向工程:

1.5.1 Hibernate反向工程:

步骤一:创建一个数据库视图:

步骤二:新建工程:

步骤三:反向工程.回到数据库视图:

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-02-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java帮帮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档