Hibernate的一级缓存:
介绍:
Hibernate向一级缓存放入数据的时候, 同时复制一份数据存放在Hibernate的快照当中, 当使用commit的方法进行提交事务的时候, 会清理session的以及缓存。 这时会使用OID判断一级缓存中的对象和快照中的对象是否一致,如果两个对象当中的属性发生变化, 则执行update语句, 将缓存当中的数据同步到数据库当中。 并且更新快照: 如果一致, 则不执行update语句。 Hibernate的一级缓存的作用就是确保一级缓存当中的数据和数据库中的数据一致。
1: 缓存: Hibernate, 以及一级缓存, 二级缓存, 延迟加载等提供的一种优化手段。 提高效率。
一级缓存: Session缓存:
不能够被卸载: 绑定在Session对象上、
他的生命周期, 和Session相同。
二级缓存: SessionFactory的缓存, 要想使用, 必须配置。
默认情况不能使用。
2: Session缓存的原理
(1)get load方法的时候, 先去缓存当中查找, 缓存当中没有数据。
此时发送select 语句到数据库, 进行数据的查询。 查询出来的数据放在一级缓存当中。
Session本质上是一个集合:
当再次调用get load 方法, 直接从缓存当中获得数据。
(2) session 代用close方法, session被关闭, 一级缓存就清空。
3: 验证一级缓存的存在:
( 持久化类能自动更新数据库依赖于一级缓存和快照)
get();
get(); //不在发送sql语句了:
package com.yidongxueyuan;
import java.io.Serializable;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.Test;
import com.yidongxueyuan.domain.Customer;
import com.yidongxueyuan.utils.HibernateUtils;
public class TestSession {
//清空一级缓存:
@Test
public void testName2() throws Exception {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//第一次查询:会发送sql语句
Customer customer = session.get(Customer.class, 2L);
System.out.println(customer.getCust_name());
//customer 从 session当中清空:
// session.evict(customer);
//clear:
// session.clear();
tx.commit();
session.close();
System.out.println(customer.getCust_name());//customer 这个对象是一个游离态:
}
//验证了一级缓存的存在:
@Test
public void testName() throws Exception {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
//第一次查询:会发送sql语句
Customer customer = session.get(Customer.class, 2L);
System.out.println(customer.getCust_name());
//不会发送sql 语句, 从缓存当中直接获得该对象:
Customer customer2 = session.get(Customer.class, 2L);
System.out.println(customer2.getCust_name());
System.out.println(customer == customer2);// true
tx.commit();
session.close();
System.out.println(customer.getCust_name());//customer 这个对象是一个游离态:
}
// 获得ThreadLocal当中的session对象:
/*
* ThreadLocal 管理的session对象不能直接使用: 需要在核心的配置文件当中配置:
*
*/
@Test
public void testName3() throws Exception {
//获得了工厂:
SessionFactory factory = HibernateUtils.getSessionFactory();
//通过工厂获得ThreadLocal当中的session对象:
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = session.get(Customer.class, 2L);
System.out.println(customer.getCust_name());
tx.commit();
// session.close();
}
}
4: 清空一级缓存:
evict(obj);
clear();
close();
三: Hibernate 的事务:
1: 什么事务?
一组逻辑操作单元,要么成功要么失败。
2:事务的特性:
ACID:
A: 原子性: 成功, 失败‘;
C: 一致性: A+B =2000 A+B= 2000
I: 隔离性: 事务之间彼此独立, 互不干扰。
D: 持久性。:
3: 事务的隔离级别:
四个隔离级别:
Read Uncommitted : 各个错误都会出现:
read committed : 防住脏读, 其他的都会发生。
repeatableread : 防住脏读,不可重复读: 可能发生幻读。
Serializable : 全都防住。
4: 不考虑隔离级别的情况下会出现错误的数据:
脏读:
不可重复读:
幻读(虚读):
5: 设置隔离级别: 防止错误数据的发生:
ORACLE: read committed
Mysql: repeatableread
thread
6: Mysql : 可重复读
是一个错误的情况还是正确的情况 ? 正确!
Hibernate管理事务:
Hibernate内存提供了ThreadLocal管理session : 默认情况不能使用:
使用是为了保证service的session和 dao层的session是同一个
使用遵循如下的步骤:
(1)在Hibernate的核心配置文件当中配置Thread:
(2)在HibernateUtil当中提供一个方法:
public static Session getCurrentSession(){
return factory.getCurrentSession(); //从本地线程当中获得了一个session对象:
}
(3)获得session:
Session session = HibernateUtil.getCurrentSession();//从本地线程当中获得了一个session对象:
事务应该设置在哪一层?
service层:
理由: 自己想也能想到啊。
service层主要负责业务,事务属于业务。
dao层两组操作必须同时完成:
Query接口:
1: 能查所有的记录:
步骤: 获得一个Query 接口: 通过session对象获得;
不需要手动关闭session(否则会报错),hibernate会自动帮你关闭,
Query接口:
1: 查询列表: list 方法: List
2: 条件查询:
session.createQuery(from Customer where 属性的名称= ?);
session.createQuery(from Customer where 属性的名称= :value);
query.setInt(0,value);
query.setString(1,value);
query.setParamer(0,value);//推荐使用:
3:分页查询:
select * from customer where xxxx limit index, count;
session.createQuery(from Customer );
query.setFirstResult();// index
query.setMaxResult(count);
4: 总记录数:
session.createQuery(“select count(*) from Customer”);
Object obj = query.uniqueResult();//获得一个唯一的值:
package com.yidongxueyuan;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;
import com.yidongxueyuan.domain.Customer;
import com.yidongxueyuan.utils.HibernateUtils;
public class TestAPI {
//测试Query接口:
@Test
public void testName() throws Exception {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//获得Query接口: HQL
// Query query = session.createQuery("select c from Customer c");
/*
* 查询: 查询所有:
* list:
*/
/* List<Customer> list = query.list();
System.out.println(list);*/
/*
* 条件查询:
* 使用是占位符:
*/
/* Query query = session.createQuery("select c from Customer c where cust_name =? ");
//设置值:
// query.setString(0, "HQL");
query.setParameter(0, "%HQL%");//推荐
List<Customer> list = query.list();
System.out.println(list);*/
/*
* 按名称设置值:
*/
/* Query query = session.createQuery("select c from Customer c where cust_name =:name and cust_id=:id ");
//设置参数的值:
query.setParameter("name", "HQL");
query.setParameter("id", 4L);
List<Customer> list = query.list();
System.out.println(list);
*/
/*
* 分页查询:
*/
/* Query query = session.createQuery("select c from Customer c ");
query.setFirstResult(4);
query.setMaxResults(5);
List<Customer> list = query.list();
System.out.println(list);
tx.commit();*/
// session.close();//不需要手动管理: 原因: 当线程执行完毕后, Hibernate已经关闭session对象: 不用再次手动关闭。 再次关闭异常。
/*
* select count(*) from customer;
*/
Query query = session.createQuery("select count(*) from Customer c ");
Long count = (Long) query.uniqueResult();
System.out.println(count);
}
}