1.对象的几种状态
在所有之前,说明一下,对于hibernate,它的对象有三种状态,transient、persistent、detached
下边是常见的翻译办法:
transient:瞬时态或者临时态
(new DeptPo(1,”行政部”,20,”行政相关”),该po的实例和session没有关联,该po的实例处于transient)
persistent:持久化状态
(和数据库中记录想影射的Po实例,它的状态是persistent, 通过get和load等得到的对象都是persistent)
detached:脱管状态或者游离态
(1)当通过get或load方法得到的po对象它们都处于persistent,但如果执行delete(po)时(但不能执行事务),该 po状态就处于detached, (表示和session脱离关联),因delete而变成游离态可以通过save或saveOrUpdate()变成持久态
(2)当把session关闭时,session缓存中的persistent的po对象也变成detached
因关闭session而变成游离态的可以通过lock、save、update变成持久态
持久态实例可以通过调用 delete()变成游离状态。
通过get()或load()方法得到的实例都是持久化状态的。
游离状态的实例可以通过调用lock()或者replicate()进行持久化。
save()和persist()将会引发SQL的INSERT,delete()会引发SQLDELETE,
而update()或merge()会引发SQL UPDATE。对持久化(persistent)实例的修改在刷新提交的时候会被检测到,它也会引起SQL UPDATE。
saveOrUpdate()或者replicate()会引发SQLINSERT或者UPDATE
可以通过session提供的方法用于改变对象的状态。
save()方法:
1.使一个临时对象成为持久化对象。
2.为对象分配ID。
3.在 flush缓存的时候发送一条insert语句。
4.save之前设置的ID是无效的。
5.持久化对象的ID是不可修改的。
@Test
public void testSave() {
News news = new News();
news.setAuthor("wenyu2");
news.setDate(new Date());
news.setTitle("php");
news.setId(23);//该行设置无效
System.out.println(news);
session.save(news);
System.out.println(news);
news.setId(45);//改行抛出异常。
persist()方法:
与save方法类似的是persist()方法, persist()方法也可以执行insert操作,但是跟save的区别是,若在persist之前设置了ID值, 则抛出异常,不会insert操作。
@Test
public void testPersist() {
News news = new News();
news.setAuthor("wangwu");
news.setDate(new Date());
news.setTitle("py");
news.setId(34);//抛异常,不会执行insert操作。
session.persist(news);
}
get()方法:该方法会立即查询加载数据库中的对象(立即执行select语句)。但是若是该记录在数据库中不存在那么返回一个null(没有即没有很直接)。
@Test
public void testGet() {
News news = (News) session.get(News.class, 4);
session.close();//若是手动关闭session,下面的打印也会成功。
System.out.println(news);
}
Load()方法:该方法功能和get相同,但是属于延迟加载的方法。
也就是说,执行load方法之后,若是不使用该对象那么不会执行select语句,仅仅返回一个代理对象。与此同时若是查询的记录在数据库中不存在,那么会抛出异常(找不到对象),可以理解为返回代理对象之后,该代理对象无法找到与之匹配的真实对象,即抛异常。
若是在使用对象之前手动关闭了session,在使用对象的时候会抛出懒加载异常。而get却是可以打印出来。
@Test
public void testLoad() {
News news = (News) session.load(News.class, 4);
System.out.println(news.getClass().getName());
session.close();
System.out.println(news);//调用的时候抛出懒加载异常。
}
update方法:
1.若更新一个持久化对象,不需要显示的调用update方法,因为在Transaction 的commit方法之前会先执行flush操作(出发update语句)。
2.当session关闭或者执行了evict方法,将对象从session 缓存中移除,那么该对象处于游离状态,此时需要显示调用update()方法,这个update()显示调用的时候,不论对象的属性是否发生变化都会执行update语句,在跟触发器协同工作的时候,为了避免这个问题,我们可以使用在hbm.xml文件中设置select-before-date值为true,检测是否有改变,若是没有改变那么不会发送update语句。(该方式不常用)。
若数据表中没有该记录,但是还是执行update的话,会导致异常。
当update方法关联一个游离状态的对象时,如果session中已经存在相同ID的持久化对象,会抛异常,因为session 中不能存在两个OID相同的对象。
@Test
public void testUpdate() {
News news = (News) session.get(News.class, 4);
transaction.commit();
session.close();// 至此news对象是一个游离状态的。
// news.setId(6);//该行会抛异常,ID在数据表中不存在。
session = sessionFactory.openSession();
transaction = session.beginTransaction();
// news.setAuthor("JDBC");// news既不在原来的session缓存中,也不在新的缓存中。
// News news2=(News)session.get(News.class, 5);//
session.update(news);// 也就是需要通过显示的执行update方法,将该对象变为持久状态。
}
saveOrUpdate()方法:
根据是否有OID 来判断是采用save操作还是update操作。 若OID不为空但是没有对应的记录,会抛异常。
@Test
public void testSaveOrUpdate() {
News news = (News) new News("FF", "ff", new Date());
news.setId(34);//若该ID在数据库中没有对应的记录,抛异常。
session.saveOrUpdate(news);
}
delete方法:
可删除一个游离对象,也可以删除一个持久化对象。session 的delete方法处理过程:
计划执行一条delete语句,把对象从session缓存中删除,该对象成为删除状态。
hibernate.use.identifier.rollback属性,默认值为false,若设置为true,将改变delete行为,那么会把对象的OID置为空,成为临时对象。
@Test
public void testDelete() {
News news = (News) session.get(News.class, 11);
session.delete(news);
// session.update(news);//删除状态的不可以进行update操作。
System.out.println(news);
}
Evict()方法:
@Test
public void testEvict() {
News news1 = (News) session.get(News.class, 9);
News news2 = (News) session.get(News.class, 8);
news1.setTitle("uu");
news2.setTitle("mm");
session.evict(news2);// 从缓存中移除对象,该对象成为游离状态对象。
session.update(news2);// 该对象若是要update的话,需要显示的调用,因为该对象已经属于游离对象。
}