知识点2: session概述
Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口,它提供了基本的保存,更新, 删除和加载Java对象的方法.
知识点3:理解session的缓存
在
Session
接口的实现中包含一系列的
Java
集合
,
这些
Java
集合构成了
Session
缓存
.
只要
Session
实例没有结束生命周期
,
存放在它缓存中的对象也不会结束生命周期
当
session
的
save()
方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图
load()
对象时,会判断缓存中是否存在该对象,有则返回。没有在查询数据库
知识点4:清理session的缓存
Session
具有一个缓存
,
位于缓存中的对象称为持久化对象
,
它和数据库中的相关记录对应
. Session
能够在某些时间点
,
按照缓存中对象的变化来执行相关的
SQL
语句
,
来同步更新数据库
,
这一过程被称为清理缓存
(flush)
默认情况下
Session
在以下时间点清理缓存:
•
当应用程序调用
Transaction
的
commit
()
方法的时
,
该方法先清理缓存
(session.flush())
,然后在向数据库提交事务
(tx.commit())
•
当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先清理缓存,以保证查询结果能够反映持久化对象的最新状态
•
显式调用
Session
的
flush()
方法
.
区别:
flush:进行清理缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步执行一些列sql语句,但不提交事务,;
commit:先调用flush()方法,然后提交事务.则意味着提交事务意味着对数据库操作永久保存下来。
reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.
clear:清空缓存,等价于list.removeAll();
知识点5:在hibernate中java对象的状态
Hibernate 把对象分为 4 种状态: 持久化状态, 临时状态, 游离状态, 删除状态.
Session 的特定方法能使对象从一个状态转换到另一个状态
知识点15: 操纵持久化对象-get() load()
都可以根据给定的
OID
从数据库中加载一个持久化对象
区别
:
•
当数据库中不存在与
OID
对应的记录时
, load()
方法抛出
ObjectNotFoundException
异常
,
而
get()
方法返回
null
•
两者采用不同的延迟检索策略
示例代码:
javabean 及 配置文件参考上篇blog的 Customer.java Order.java Customer.hbm.xml hibernate.cfg.xml Order.hbm.xml
知识点示例代码:
AppFlushClearRefreshCommit.java
package cn.itcast.state;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class AppFlushClearRefreshCommit {
private static SessionFactory sf=null;
static{
Configuration config=new Configuration();
config.configure("cn/itcast/state/hibernate.cfg.xml");
config.addClass(Customer.class);
config.addClass(Order.class);
sf=config.buildSessionFactory();
}
/*
* 知识点4_1:清理session的缓存 测试flush方法的使用
*/
@Test
public void testFlush(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
Customer c=new Customer();
c.setName("曹操");
session.save(c);
/*
* 清理缓存,刷新session的一级缓存中数据到数据库中,让缓存中的数据跟数据库同步 方向缓存--->数据库
* 缓存中的数据不丢失
*/
session.flush(); //会产生insert语句,此时已经在数据库中,但数据库还没有确认
tx.commit(); //数据库确认插入的数据
session.close();
}
/*
* 知识点4_2:清理session的缓存 测试flush和clear方法的使用
*/
@Test
public void testFlushClear(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//从数据库查询出的客户放置到session的一级缓存中
Customer c4=(Customer)session.get(Customer.class, 4); //select
//清理缓存,缓存中的数据不丢失
session.flush();
//从session的一级缓存中获取要查询的数据
Customer c5=(Customer)session.get(Customer.class, 4); //不会产生select语句
//清空缓存,session的一级缓存中的数据丢失
session.clear();
//缓存中已经没有数据了,需要重新查询数据库
Customer c6=(Customer)session.get(Customer.class, 4); //会产生select语句
tx.commit(); //数据库确认插入的数据
session.close();
}
/*
* 知识点4_4:清理session缓存 测试refresh方法的使用
*/
@Test
public void tesRefresh(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
Customer c4=(Customer)session.get(Customer.class, 4); //select
c4.setName("马超");
//刷新数据库中的数据和缓存中的同步,方法向从数据库----> 缓存,产生select语句
session.refresh(c4);
tx.commit(); //数据库确认插入的数据
session.close();
}
/*
* 知识点4_5:清理session的缓存(设置缓存的清理模式)
*/
@Test
public void testCacheMode11(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//设置缓存的模式是自动模式
Customer c=new Customer();
c.setName("秦琼");
session.save(c);
tx.commit(); //产生insert语句
session.close();
}
/*
* 知识点4_5:清理session的缓存(设置缓存的清理模式)
*/
@Test
public void testCacheMode12(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//设置缓存的模式是自动模式
Customer c=new Customer();
c.setName("秦琼");
session.save(c);
session.flush();//产生insert语句
tx.commit();
session.close();
}
/*
* 知识点4_5:清理session的缓存(设置缓存的清理模式)
*/
@Test
public void testCacheMode13(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//设置缓存的模式是从不清理缓存
session.setFlushMode(FlushMode.NEVER);
Customer c=new Customer();
c.setName("秦琼");
session.save(c);
//该方法不清理缓存,不会产生insert语句,此时数据不能插入到数据库中
tx.commit();
session.close();
}
/*
* 知识点4_5:清理session的缓存(设置缓存的清理模式)
*/
@Test
public void testCacheMode14(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//设置缓存的模式是从不清理缓存
session.setFlushMode(FlushMode.NEVER);
Customer c=new Customer();
c.setName("秦琼");
session.save(c);
//该方法清理缓存
session.flush(); //产生insert语句
//该方法不清理缓存
tx.commit();
session.close();
}
/*
* 知识点4_5:清理session的缓存(设置缓存的清理模式)
*/
@Test
public void testBatchData(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
//设置缓存的模式是从不清理缓存
session.setFlushMode(FlushMode.NEVER);
for(int i=0;i<100000;i++){
Customer c=new Customer();
c.setName("朱仝"+i);
session.save(c);
if(i%1000==0){
//清理缓存,数据已经存在数据库,就是没有确认
session.flush();
//清空缓存
session.clear();
}
}
//清理缓存
session.flush();
//该方法不清理缓存
tx.commit();
session.close();
}
}
AppState.java
package cn.itcast.state;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class AppState {
private static SessionFactory sf = null;
static {
Configuration config = new Configuration();
config.configure("cn/itcast/state/hibernate.cfg.xml");
config.addClass(Customer.class);
config.addClass(Order.class);
sf = config.buildSessionFactory();
}
/*
* 知识点5:临时对象(transient) 对象的状态
*/
@Test
public void teststate() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//刚刚创建一个对象,此时就是临时对象,OID=null
Customer c = new Customer();
c.setName("曹操");
System.out.println("c.getId() "+c.getId()); //null
//此时customer对象变为持久对象(持久对象有OID,OID不为空)处于session的缓存中
session.save(c);
System.out.println("c.getId() "+c.getId()); //存在值
tx.commit(); // 数据库确认插入的数据
session.close(); //此时没有一级缓存了
//session关闭后,此时c引用的对象转化为游离对象 不再处于 Session 的缓存中
System.out.println(c.getId()+" "+c.getName());
//此时对象不再被引用,被jvm回收
c=null;
/****************************************************************************************************************/
session = sf.openSession();
tx = session.beginTransaction();
//c1在session的一级缓存中存在 是持久对象
Customer c1=(Customer)session.get(Customer.class, 5);
//删除c1对象
session.delete(c1);
//此时c1变为删除对象
tx.commit(); // 数据库确认插入的数据
session.close(); //此时没有一级缓存了
//session关闭后,此时c1为游离对象
/****************************************************************************************************************/
}
/*
* 知识点5:临时对象(transient) 对象的状态
* * evict()方法:该方法能将持久对象转化为游离对象
*/
@Test
public void testEvict() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//c1在session的一级缓存中存在 是持久对象
Customer c1=(Customer)session.get(Customer.class, 5); //产生select语句
//直接从session的一级缓存中查询数据
Customer c2=(Customer)session.get(Customer.class, 5); //不产生select语句
//将session一级缓存中的对象转化为游离对象,此时该对象在session的一级缓存中不存在
session.evict(c1);
//该方法能将游离对象再转化为持久对象,此时该对象有存在session的一级缓存中
session.update(c1);
//在缓存中不存在该对象,所以要查询数据库
Customer c3=(Customer)session.get(Customer.class, 5); //不产生select语句
tx.commit(); // 数据库确认插入的数据
session.close(); //此时没有一级缓存了
}
}
AppMethod.java
package cn.itcast.state;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class AppMethod {
private static SessionFactory sf = null;
static {
Configuration config = new Configuration();
config.configure("cn/itcast/state/hibernate.cfg.xml");
config.addClass(Customer.class);
config.addClass(Order.class);
sf = config.buildSessionFactory();
}
/*
* 知识点12: 操纵持久化对象-save()
*/
@Test
public void testSave() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Customer c=new Customer();
c.setId(3); //没有用途
c.setName("西门庆");
session.save(c);
tx.commit();
session.close();
}
/*
* 知识点13_1: 操纵持久化对象-update()
*/
@Test
public void updagePersission() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//持久对象
Customer c=(Customer)session.get(Customer.class, 7);
//游离对象
session.evict(c);
//游离对象---->持久对象 ---执行update语句
session.update(c);
tx.commit();
session.close();
}
/*
* 知识点13_2: 操纵持久化对象-update()
* * 在customer.hbm.xml文件的class标签中增加 select-before-update="true"(在执行更新之前查询)
* * 目的:把要更新的信息又防止到session的一级缓存中,快照有一份
* * 在更新时,哪缓存中的数据和快照比对,没有变化,不再产生update语句
*/
@Test
public void updagePersissionClass() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//持久对象
Customer c=(Customer)session.get(Customer.class, 7);
//游离对象
session.evict(c);
//游离对象---->持久对象 ---执行update语句
session.update(c);
tx.commit();
session.close();
}
/*
* 知识点13_3: 操纵持久化对象-update()
*/
@Test
public void updagePersissionOId() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//查询数据库 c1持久对象
Customer c1=(Customer)session.get(Customer.class, 7);
//c1游离对象
session.evict(c1);
//查询数据库 c2持久对象
Customer c2=(Customer)session.get(Customer.class, 7);
//c1持久对象
session.update(c1);
tx.commit();
session.close();
}
/*
* 知识点13_4: 操纵持久化对象-update()
*/
@Test
public void updagePersissionWithNoData() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//查询数据库 c1持久对象
Customer c1=(Customer)session.get(Customer.class, 7);
//c1游离对象
session.evict(c1);
System.out.println("cccccccccccccccc");
//手动删除数据
//c1持久对象
session.update(c1);
tx.commit();
session.close();
}
/*
* 知识点14_2: 操纵持久化对象-saveOrupdate()
*/
@Test
public void SaveOrUpdateTransient() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//临时对象
Customer c=new Customer();
c.setName("西门庆");
session.saveOrUpdate(c);
tx.commit();
session.close();
}
/*
* 知识点14_3: 操纵持久化对象-saveOrupdate()
* 如果是游离对象就用update方法
*/
@Test
public void updagePersissionDetached() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//查询数据库 c1持久对象
Customer c1=(Customer)session.get(Customer.class, 6);
//c1游离对象
session.evict(c1);
//c1持久对象 执行update方法
session.saveOrUpdate(c1);
tx.commit();
session.close();
}
/*
* 知识点14_4: 操纵持久化对象-saveOrupdate()
*/
@Test
public void updagePersissionPersiss() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//查询数据库 c1持久对象
Customer c1=(Customer)session.get(Customer.class, 6);
//c1持久对象 不会产生update语句
session.saveOrUpdate(c1);
tx.commit();
session.close();
}
/*
* 知识点14_5: 操纵持久化对象-saveOrupdate()
* saveOrUpdate(c)中判定对象为临时对象的标准
* * 如果Id为Integer类型(private Integer id)
* * 如果Id==null执行save操作
* * 如果Id!=null执行update操作
* * 如果javaBean中id为int类型(private int id;)此时id的默认值为0
* 在Customer.hbm.xml文件 配置<id name="id" type="integer" unsaved-value="0">增加unsaved-value="0"
* * 如果javaBean中id属性的值与unsaved-value="0"相同,执行insert操作
* * 如果javaBean中id属性的值与unsaved-value="0"不相同,执行update操作
*/
@Test
public void SaveOrUpdateUnsaved() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
//临时对象
Customer c=new Customer();
c.setName("西门庆");
session.saveOrUpdate(c);
System.out.println("c.getId() "+c.getId());
tx.commit();
session.close();
}
/*
* 知识点15: 操纵持久化对象-get() load()
* * 区别
* * 相同点:都是通过id查询对象
* * 不同点;
* * 如果id在数据库中不存在get返回null,load抛出异常
* * get方法总是立即加载,load可以配置延迟和立即两种(后面讲)
*
*/
@Test
public void getOrLoad() {
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
Customer c1=(Customer)session.load(Customer.class, 14);
System.out.println("c1 = "+c1);
tx.commit();
session.close();
}
}