Hibernate的开发理论来源就是EJB 2.x Entity Bean(实体Bean),在实体Bean里面有一个特点,每当调用了对象中的setter()方法,那么就可以自动的进行数据更新。所以Hibernate本身也具备此类操作,那么在Hibernate之中为了更好的理解POJO类的对象所处的状态,专门提供有三种状态: (1)瞬时态(Transient):对象保存在内存之中,并没有在数据库之中进行存储,也就是说如果对象一直没有存储,那么就有可能被GC回收,回收之后就像不存在一样; (2)持久态(Persistent):将内存中的对象保存在数据库之中,或者某一个对象通过数据库读取,此时Session如果没有关闭,那么就是持久态,持久态的最大特征就是属性的变化将引起数据库的变化; (3)游离态(Detached):如果Session关闭了,那么已经读取出来的数据就变为游离态,这个时候对象保存在内存之中,如果长时间不使用将被GC回收,与瞬时态最大区别只有一点:此时数据库之中有对应数据。 范例:瞬时态——此时没保存
package org.lks.test; import java.text.ParseException; import java.text.SimpleDateFormat; import org.lks.pojo.Member; public class TestMemberDemo { public static void main(String[] args) throws ParseException { Member member = new Member(); member.setMid("3181301102"); member.setMname("hhy"); member.setMage(20); member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21")); member.setMsalary(10000.0); member.setMnote("big fool!"); } }整个的代码操作过程之中,Member对象只存在于内存之中,并没有利用Session进行保存。 范例:由瞬时态变为持久态——只需要使用save()方法保存
package org.lks.test; import java.text.ParseException; import java.text.SimpleDateFormat; import org.lks.dbc.HibernateSessionFactory; import org.lks.pojo.Member; public class TestMemberDemo { public static void main(String[] args) throws ParseException { Member member = new Member(); member.setMid("31813011021"); member.setMname("hhy"); member.setMage(20); member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21")); member.setMsalary(10000.0); member.setMnote("big fool!"); //进行数据库保存,所以由瞬时态变为了持久态 System.out.println(HibernateSessionFactory.getSession().save(member)); HibernateSessionFactory.getSession().beginTransaction().commit(); } } 31813011021 Hibernate: insert into hedb.member (mage, mbirthday, mname, mnote, msalary, mid) values (?, ?, ?, ?, ?, ?)如果某一个对象处于持久态的状态下,只需要调用setter方法就可以更新了。 范例:观察持久态的操作形式
package org.lks.test; import java.text.ParseException; import java.text.SimpleDateFormat; import org.lks.dbc.HibernateSessionFactory; import org.lks.pojo.Member; public class TestMemberDemo { public static void main(String[] args) throws ParseException { Member member = new Member(); member.setMid("31813011022"); member.setMname("hhy"); member.setMage(20); member.setMbirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1999-08-21")); member.setMsalary(10000.0); member.setMnote("big fool!"); //进行数据库保存,所以由瞬时态变为了持久态 System.out.println(HibernateSessionFactory.getSession().save(member)); HibernateSessionFactory.getSession().beginTransaction().commit(); //此时Session并没有关闭 member.setMsalary(100.0); HibernateSessionFactory.getSession().beginTransaction().commit(); HibernateSessionFactory.closeSession(); System.exit(0); } } 31813011022 Hibernate: insert → HibernateSessionFactory.getSession().save(member) into hedb.member (mage, mbirthday, mname, mnote, msalary, mid) values (?, ?, ?, ?, ?, ?) Hibernate: update → member.setMsalary(100.0); hedb.member set mage=?, mbirthday=?, mname=?, mnote=?, msalary=? where mid=?因为现在Session没有关闭,对象属于持久态的状态,所以可以直接利用setter更新数据。
实际上在Session里面存在有get()与load()两个操作方法,这两个操作方法都是根据ID进行数据查询,如果说现在使用ID查询的话,那么对象也处于持久态(前提:不关闭Session)。 范例:观察持久态
package org.lks.test; import org.lks.dbc.HibernateSessionFactory; import org.lks.pojo.Member; public class TestMemberGet { public static void main(String[] args) { //在Session没有关闭之前处于持久态 Member vo = (Member) HibernateSessionFactory.getSession().get(Member.class, "3171301102"); //此时Session现在并没有关闭,对象为持久态 vo.setMsalary(10000.0); vo.setMnote("super big fool!"); HibernateSessionFactory.getSession().beginTransaction().commit(); } } Hibernate: select → HibernateSessionFactory.getSession().get(Member.class, "3171301102"); member0_.mid as mid1_0_0_, member0_.mage as mage2_0_0_, member0_.mbirthday as mbirthda3_0_0_, member0_.mname as mname4_0_0_, member0_.mnote as mnote5_0_0_, member0_.msalary as msalary6_0_0_ from hedb.member member0_ where member0_.mid=? Hibernate: update → vo.setMsalary(10000.0); vo.setMnote("super big fool!"); hedb.member set mage=?, mbirthday=?, mname=?, mnote=?, msalary=? where mid=?如果在进行一些登录操作的时候,可能会更新某一个用户最后一次登录日期,那么就可以利用持久态实现这类的操作。 范例:游离态
package org.lks.test; import org.lks.dbc.HibernateSessionFactory; import org.lks.pojo.Member; public class TestMemberDetached { public static void main(String[] args) { //在Session没有关闭之前处于持久态 Member vo = (Member) HibernateSessionFactory.getSession().get(Member.class, "3171301102"); //此时Session关闭了,关闭之后变为游离态 HibernateSessionFactory.closeSession(); //此时Session现在并没有关闭,对象为持久态 vo.setMsalary(10000.0); vo.setMnote("super big fool!"); HibernateSessionFactory.getSession().beginTransaction().commit(); } } Hibernate: select → HibernateSessionFactory.getSession().get(Member.class, "3171301102"); member0_.mid as mid1_0_0_, member0_.mage as mage2_0_0_, member0_.mbirthday as mbirthda3_0_0_, member0_.mname as mname4_0_0_, member0_.mnote as mnote5_0_0_, member0_.msalary as msalary6_0_0_ from hedb.member member0_ where member0_.mid=?因为现在变为了游离态,所以所有数据的修改不会影响到数据库中的实体数据。
口诀: (1)瞬时态与游离态无法更新数据; (2)持久态可以更新,但是必须在Session关闭之前完成更新; 切换方法: (1)瞬时态→持久态:save()方法、update()方法; (2)持久态→游离态:关闭Session; (3)游离态→瞬时态:delete()操作;
面试题:请解释Hibernate对象的三种状态? (1)Hibernate对象数据分别有:瞬时态、持久态、游离态; (2)瞬时态指的是对象只在内存中保存,数据库没有对应数据; (3)持久态指的是在对象保存或者取得之后不关闭Session的情况下,可以利用setter进行数据修改; (4)游离态指的是对象读取完成或保存成功之后关闭了Session后的状态,此时数据库有对应数据。