hibernate对象状态有三种
瞬时(临时)对象
持久化对象
脱离(游离)对象
临时状态(transient):刚刚用new语句创建,还没有被持久化,不处于Session的缓存中。处于临时状态的Java对象被称为临时对象。(数据库和session中都不存在)
持久化状态(persistent):已经被持久化,加入到Session的缓存中。处于持久化状态的Java对象被称为持久化对象。(数据库和session中都存在)
游离状态(detached):已经被持久化,但不再处于Session的缓存中。处于游离状态的Java对象被称为游离对象。(数据库中存在,而session中不存在)
临时状态与游离状态的区别:一般情况下,临时状态的对象无主键并且没有持久化,游离状态的对象有主键没有被持久化
对象转换关系图:
代码示例
/**
* save:由临时状态-->持久化状态 1.save方法执行后,必须保证id存在, 所以根据主键生成方式的不同向数据库发送不同的sql语句
* 1>由hibernate生成主键 发送select 调用完flush才发送insert 2>由底层数据库生成 发送insert
* 2.save之前给临时状态设id,没卵用 3.持久化状态的对象不允许修改id
*/
@Test
public void testSave() {
News news = new News("yinhe", "hebi", new Date());
news.setNewsId(11);
session.save(news);
}
/**persist:由临时状态-->持久化状态
* 与save的不同: 如果在persist之前 设置了临时对象的id 那么会抛出异常
*/
@Test
public void testPersist(){
News news = new News("yinhe", "hebi", new Date());
news.setNewsId(11);
session.persist(news);
}
/**
* 游离状态-->持久化状态 get和load: 1.get直接检索 load延迟检索
* get方法执行后会直接返回一个news对象,而load返回的是news对象的代理对象 当使用news时,再查询数据库
* 2.如果数据表没有对应的数据:
* get:返回null
* load:拋出异常
* 3.当使用news之前关闭了session:
* 1>get:不受影响,因为立即检索
* 2>load:抛出懒加载异常,
* 解决方式:在session关闭(commit)之前使用news,或者实例化news对象
* Hibernate.initialize(news1);
*/
@Test
public void testGet() {
News news1 = (News) session.get(News.class, 2);
session.getTransaction().commit();
System.out.println(news1);
}
@Test
public void testLoad() {
News news1 = (News) session.load(News.class, 2);
Hibernate.initialize(news1);
session.getTransaction().commit();
System.out.println(news1);
}
/**
* evict:持久化对象-->游离对象
*
*/
@Test
public void testEvict(){
News news1 = (News) session.get(News.class, 1);
News news2 = (News) session.get(News.class, 2);
//清除news1对应的缓存
session.evict(news2);
//查询id为7的记录,观察select语句发送与否
News news3 = (News) session.get(News.class, 2);
}
/**Update:将游离状态-->持久化状态
* 如果更新持久化状态的对象,我们 不需要显式的调用update语句 在commit时,
* 会通过flush方法将缓存中的对象更新到数据库中,通过flush,可能会发送update语句
* 更新游离对象:
* 1.确保更新的对象的id在数据表中,如果不在,抛出异常
* 2.不论和数据库记录是否一致,都发update命令,那么如何
* 防止都发送update呢?
* 了解:在对象关系映射文件中的class节点添加select-before-update属性,默认为false
* 设置为true后,会在每次update之前查询缓存中的内容是否与数据库记录一致,
* 如果一致不再发送update语句
* 3.session中不能有两个id相同的同一个类对象
*/
@Test
public void testUpdate(){
//更新持久化对象
// News news1 = (News) session.get(News.class, 2);
// news1.setTitle("asd");
//1.确保更新的对象的id在数据表中,如果不在,抛出异常
// News news = new News("qwe", "777", new Date());
// news.setNewsId(2);
// session.update(news);
//2.
// News news1 = (News)session.get(News.class, 2);
// session.clear();
// session.update(news1);
//3.
News news1 = (News) session.get(News.class, 2);
news1.setContent("aaaaaa");
session.clear();
News news2 = (News) session.get(News.class, 2);
session.update(news1);
}
/**
* saveOrUpdate()
* 1.临时对象:save
* 游离对象:update 如果id和数据库不对应,抛出异常
* 2.unsaved-value 如果设成50,
* 会将id为50的游离对象看作临时对象
*/
@Test
public void saveOrUpdate(){
News news1 = new News("1", "2", new Date());
news1.setNewsId(2);
session.saveOrUpdate(news1);
}
/**
* 删除:delete 如果删除一个id在数据库中不对应的 那么会抛出异常
* 持久化对象:不受unsaved-value影响
* 游离对象:受unsaved-value影响
* 如果游离对象id与unsaved-value一致,
* 那么系统会将此游离对象作为临时对象
*/
@Test
public void delete(){
News news1 = new News("1", "2", new Date());
news1.setNewsId(2);
session.delete(news1);
// News news2 = (News)session.get(News.class, 10);
// session.delete(news2);
}