Hibernate -- 操作持久化对象
知识点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(); } }