Hibernate中的对象有3中状态,瞬时对象(TransientObjects)、持久化对象(PersistentObjects)和离线对象(DetachedObjects也叫做脱管对象)。

下图3.1显示了瞬时对象、持久化对象和离线对象之间的关系以及它们之间的转换。
图3.1
临时状态:由Java的new命令开辟内存空间的java对象也就是普通的java对象,如果没有变量引用它它将会被JVM收回。临时对象在内存中是孤立存在的,它的意义是携带信息载体,不和数据库中的数据由任何的关联。通过Session的save()方法和saveOrUpdate()方法可以把一个临时对象和数据库相关联,并把临时对象携带的信息通过配置文件所做的映射插入数据库中,这个临时对象就成为持久化对象。
持久化状态:持久化对象在数据库中有相应的记录,持久化对象可以是刚被保存的,或者刚被加载的,但都是在相关联的session声明周期中保存这个状态。如果是直接数据库查询所返回的数据对象,则这些对象和数据库中的字段相关联,具有相同的id,它们马上变成持久化对象。如果一个临时对象被持久化对象引用,也立马变为持久化对象。
如果使用delete()方法,持久化对象变为临时对象,并且删除数据库中相应的记录,这个对象不再与数据库有任何的联系。
持久化对象总是与Session和Transaction关联在一起,在一个session中,对持久化对象的操作不会立即写到数据库,只有当Transaction(事务)结束时,才真正的对数据库更新,从而完成持久化对象和数据库的同步。在同步之前的持久化对象成为脏对象。
当一个session()执行close()、clear()、或evict()之后,持久化对象就变为离线对象,这时对象的id虽然拥有数据库的识别值,但已经不在Hibernate持久层的管理下,他和临时对象基本上一样的,只不过比临时对象多了数据库标识id。没有任何变量引用时,jvm将其回收。
脱管状态:Session关闭之后,与此Session关联的持久化对象就变成为脱管对象,可以继续对这个对象进行修改,如果脱管对象被重新关联到某个新的Session上,会在此转成持久对象。
脱管对象虽然拥有用户的标识id,所以通过update()、saveOrUpdate()等方法,再次与持久层关联。
下面我们就通过使用hibernate,实现对数据库的增删改查来体现三种状态之间的转换过程。
添加修改演示三种状态之间的变化
当我们建立Session都要实例化SessionFactory,所以我们把重复的代码进行封装,并且session是单线程的。我们把对session的管理,打开session,关闭session等封装到工具类中,代码如下所示。
package com.bjpowernode.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtils {
private static SessionFactory factory;
//static只初始化一次.
static
{
try{
//默认读取的是hibernate.cfg.xml 文件.
Configuration cfg = new Configuration().configure();
//建立SessionFactory.
factory = cfg.buildSessionFactory();
}catch(Exception e )
{
e.printStackTrace();
}
}
public static Session getSession()
{
//打开session.
return factory.openSession();
}
//关闭session.
public static void closeSession(Session session)
{
//判断是否为空.
//判断是否是打开状态再进行关闭.
if(session!=null)
{
if(session.isOpen())
{
session.close();
}
}
}
//返回工厂类.
public static SessionFactory getSessionFactory()
{
return factory;
}
}
Hibernate.cfg.xml代码如下所示。
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory > <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/Hibernate_session</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.show_sql">true</property> <mapping resource="com/bjpowernode/hibernate/User.hbm.xml"/> </session-factory> </hibernate-configuration>
之前我们把对表添加的操作放到普通的java类中,在这个类的main()方法中执行,如果我们再对表进行其他的操作呢?那是不是还要建立新的java类,多个方法就不容易测试了。我们使用测试工具类JUnit来做测试,来测试增删改查。首先建立源目录,在test包中放测试程序。
我们建立我们的测试程序SessionTest.java,继承TestCase类,这样我们在SessionTest.java类中测试数据库中的某个方法,方法名的规范要以test开头。我们向User表中添加一条记录如下代码所示。
package com.bjpowernode.hibernate;
import java.util.Date;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class SessionTest extends TestCase {
//测试方法以test开头.
public void testSave1()
{
Session session = null;
Transaction tx = null;
try
{
//取得session.
session = HibernateUtils.getSession();
//自己开启事务. 返回 transient的一个实例.
tx = session.beginTransaction();
//传入值.变为Transient状态.
User user = new User();
user.setName("张三");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//进行保存.执行save则对session进行管理了. 处于持久状态.
//persistent状态的对象.当对象的属性发生改变的时候,hibernate在清理
//缓存的时候(脏数据检查)的时候,会和数据库同步.
session.save(user);
user.setName("李四");
//再次提交.
tx.commit();
}catch(Exception e)
{
e.printStackTrace();
if(tx!=null)
{
// 事务回滚.
tx.rollback();
}
}finally
{
//关闭session.当关闭session时处于Detached状态.
HibernateUtils.closeSession(session);
}
}
首先是建立对象与表的会话session,开启事务session.beginTransaction(),实例化User对象,当我们User user = new User()的时候,当我们new一个对象的时候数据库是没有的,所以是Transient对象(临时对象),然后给user赋值,设置名称和密码以及其他属性。 为对象的所有属性赋值完毕,接下来保存到会话session中,拿到session执行save(user)方法。 当我们执行session的save()方法时,这个对象就被session管理了,session中有个map,会把对象放到map中,此时的对象我们就成为persistent状态(持久状态)。
接下来我们又把user中的name属性设置为“李四”,之后提交事务。我们先再会话中存储的“张三”,之后改为“李四”。try catch来扑捉异常,当执行完毕,关闭session后,对象处于detached状态(离线状态)。
我们创建数据库,利用ExportDB.java方法建立表。之后执行SessionTest的testSave1()方法,当执行到session方法的时候,表中自动生成user表的id值,并且名子为“张三”,之后再次执行,名字又变为“李四”,之后执行事务的commit()方法tx .commit ,此时控制台才发出语句,如下图3.2。
从控制台的语句中可以看出,显示发送的插入sql语句,后是update语句,首先是持久化对象user中的名字为“张三”,所以save的时候生成inset语句。此时user处于持久状态的对象,我们之后又给变了持久化对象,所以发送了一个修改语句。也就是当持久化对象发生修改时,我们再提交事务,就会把修改的全部体现出来(update语句)。
也就是我们再提交事务的时候,在清理缓存,也就是脏数据检查(内存中变了,而数据没变),要检查哪些数据是有问题的,要保持内存和数据库的同步。所以我们数据库中添加的记录,user的名字为李四(如图3.3所示)。
图3.3
如果上述代码中,我们在修改名字为李四后user.setName("李四");我们显示调用session的update()方法,session.update(),运行,会看到控制台上打印的sql语句和我们不加如session.update()打印的相同。持久化对象只要更改了,在提交事务的时候就会同步,没有必要再显示调用。
Detached状态演示
我们在执行完所有的操作,关闭session后,此时的user对象变为detached状态,此时进行操作。
代码如下所示。
public void testSave3()
{
Session session = null;
Transaction tx = null;
User user = null;
try
{
//取得session.
session = HibernateUtils.getSession();
//自己开启事务. fanhui transient的一个实例.
tx = session.beginTransaction();
//传入值.变为Transient状态.
user = new User();
user.setName("张三");
user.setPassword("123");
user.setCreateTime(new Date());
user.setExpireTime(new Date());
//进行保存.执行save则对session进行管理了. 处于持久状态.
//persistent状态的对象.当对象的属性发生改变的时候,hibernate在清理
//缓存的时候(脏数据检查)的时候,会和数据库同步.
session.save(user);
user.setName("李四");
//可以显示的调用update方法,因为此时为持久状态,调用update没有什么意义.
//再次提交.
tx.commit();
}catch(Exception e)
{
e.printStackTrace();
if(tx!=null)
{
// 事务回滚.
tx.rollback();
}
}finally
{
//关闭session.当关闭session时处于Detached状态.
HibernateUtils.closeSession(session);
}
//已经不能用以前的session了.
user.setName("王五");
try
{
//得到新的session.
session = HibernateUtils.getSession();
//开启事务.
session.beginTransaction();
//将detached状态的对象重新纳入session管理.
//此时将变为persistent状态的对象.
//persistent状态的对象,在清理缓存时,会根数据库同步.
session.update(user);
//提交事务.把内存的改变提交到数据库上.
session.getTransaction().commit();
}catch(Exception e)
{
e.printStackTrace();
session.getTransaction().rollback();
}finally
{
HibernateUtils.closeSession(session);
}
}
取得detached状态的user对象,改变这个对象的name值,user.setName("王五");之后我们再new一个新的
session,通过session开启事务,之后更新操作,session.update(user),也就是把离线的对象(或脱管对象)再纳入session管理,这样就会和数据库同步,因为session.update()就把user对象纳入session管理,user对象由离线状态变为persistent状态。
提交事务,将和数据库同步。把内存的改变体现到数据库上。控制台sql语句以及运行向表中添加记录结果如图3.4,3.5所示。
图3.4
总结
以上所述是小编给大家介绍的Hibernate持久化对象的三个状态,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# hibernate持久化对象
# 持久化对象的三种状态
# 浅谈hibernate中对象的3种状态_瞬时态、持久态、脱管态
# 浅谈Hibernate对象状态之间的神奇转换
# 离线
# 所示
# 李四
# 数据库中
# 当我们
# 相关联
# 就会
# 在此
# 类中
# 三种
# 如图
# 会把
# 小编
# 再提
# 则对
# 把对
# 的是
# 判断是否
# 有任何
# 王五
相关文章:
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
h5在线制作网站电脑版下载,h5网页制作软件?
Python文件管理规范_工程实践说明【指导】
如何登录建站主机?访问步骤全解析
建站之星安装提示数据库无法连接如何解决?
免费视频制作网站,更新又快又好的免费电影网站?
如何制作算命网站,怎么注册算命网站?
如何在香港服务器上快速搭建免备案网站?
如何选择高效稳定的ISP建站解决方案?
香港服务器网站推广:SEO优化与外贸独立站搭建策略
建站之星在线版空间:自助建站+智能模板一键生成方案
香港服务器网站生成指南:免费资源整合与高速稳定配置方案
如何规划企业建站流程的关键步骤?
c# F# 的 MailboxProcessor 和 C# 的 Actor 模型
微课制作网站有哪些,微课网怎么进?
c++如何打印函数堆栈信息_c++ backtrace函数与符号名解析【方法】
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
如何在IIS中新建站点并解决端口绑定冲突?
大连网站制作公司哪家好一点,大连买房网站哪个好?
完全自定义免费建站平台:主题模板在线生成一站式服务
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
如何在云指建站中生成FTP站点?
如何选择网络建站服务器?高效建站必看指南
制作证书网站有哪些,全国城建培训中心证书查询官网?
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
公司门户网站制作流程,华为官网怎么做?
建站之星好吗?新手能否轻松上手建站?
建站之星代理如何获取技术支持?
如何确认建站备案号应放置的具体位置?
北京网站制作公司哪家好一点,北京租房网站有哪些?
,制作一个手机app网站要多少钱?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
在线ppt制作网站有哪些,请推荐几个好的课件下载的网站?
制作网站的软件下载免费,今日头条开宝箱老是需要下载怎么回事?
网站企业制作流程,用什么语言做企业网站比较好?
C#怎么使用委托和事件 C# delegate与event编程方法
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
网站制作难吗安全吗,做一个网站需要多久时间?
建站主机选购指南与交易推荐:核心配置解析
内网网站制作软件,内网的网站如何发布到外网?
济南企业网站制作公司,济南社保单位网上缴费步骤?
jQuery 常见小例汇总
如何快速使用云服务器搭建个人网站?
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
如何获取上海专业网站定制建站电话?
公众号网站制作网页,微信公众号怎么制作?
如何将凡科建站内容保存为本地文件?
如何在局域网内绑定自建网站域名?
seo网站制作优化,网站SEO优化步骤有哪些?
如何在腾讯云免费申请建站?
*请认真填写需求信息,我们会在24小时内与您取得联系。