深入解析Java的Hibernate框架中的持久对象_java

一、持久对象生命周期
应用程序在使用Hibernate框架后,创建的持久对象会经历一整套生命周期来完成数据库的操作,其中主要的三个状态分别是瞬态(Transient)、持久化(Persistent)、脱管(detached)。这三种状态的转换是能够在应用程序中控制的,如下图:

为了能清楚的了解这几种状态,这里使用一个实例来查看下这几种状态下对象的不同,下面状态内的代码,具体步骤如下:
(1)创建Hibernate_session程序集,并添加像相应的jar包;
(2)配置Hibernate,添加相应的实体User类,及它的映射文件,并配置好相应的数据库连接;
User类文件的映射文件User.hbm.xml代码:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-4-30 15:39:33 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
 <class name="com.hibernate.User">
  <id name="id">
   <generator class="uuid"/>
  </id>
  <property name="name"/>
  <property name="password"/>
  <property name="createTime"/>
  <property name="expireTime"/>
 </class>
</hibernate-mapping> 

Hibernate数据库连接配置代码:

<?xml version="1.0" encoding="UTF-8"?>
<!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">ab12</property>
  <!-- dialect:方言,封装的底层API,类似于Runtime,将数据库转换为配置中的相应的语言 -->
  <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 

  <mapping resource="com/hibernate/User.hbm.xml"/>
 </session-factory>
</hibernate-configuration>

(3)添加静态成员sessionfactory的公共类,用来创建一个SessionFactory及其Session对象;

package com.hibernate; 

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; 

public class session { 

 private static SessionFactory factory; //声明静态局部变量SessionFactory,数据库镜像 

 static{
  try{
   //创建并获取配置数据库的配置文件,默认获取hibernate.cfg.xml
   Configuration cfg=new Configuration().configure();
   factory=cfg.buildSessionFactory(); //构建一个数据库镜像
  }catch(Exception e){
   e.printStackTrace(); //打印错误信息
  }
 } 

 public static Session getSession(){
  return factory.openSession(); //返回创建的session对象
 } 

 public static SessionFactory getSessionFactory(){
  return factory; //返回相应的SessionFactory
 } 

 //关闭session对象
 public static void closeSession(Session session){
  if(session != null){
   if(session.isOpen()){
    session.close();
   }
  }
 }
} 

(4)添加一个Source Folder,并在该文件夹内添加名称为com.hibernate的package包,并在包中添加一个名称为SessionTest的类文件。

package com.hibernate; 

import java.util.Date; 

import junit.framework.TestCase; 

import org.hibernate.Session;
import org.hibernate.Transaction; 

public class SessionTest extends TestCase { 

} 

二、状态转化方法
1、对象直接进入Persistent状态    
     
1.1 get方法
从数据库中获取一行信息,并将该信息同步到创建的对象中,该方法返回一个Object对象,如果没有查询到内容则返回null。下面的实例通过采用Session的get方法来获取一个对象,并将对象转换为实例。

public void testGet1(){
 Session session=null;
 Transaction tx = null;
 try{
  session=HibernateUtils.getSession();
  //开启事务
  tx= session.beginTransaction();
  //get加载上来的对象为持久对象
  //执行get会马上发出查询语句,如果不存在会返回null
  User user=(User)session.get(User.class,"ff80808145bc28cc0145bc28ce020002");
  System.out.println(user.getName()); 

  //persistent状态
  //persistent状态的对象,当对象的属性发生改变的时候
  //Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
  user.setName("赵柳"); 

  session.getTransaction().commit();
 }catch(Exception e){
  e.printStackTrace();
  if(tx != null){
   tx.rollback();
  }
 }finally{
  HibernateUtils.closeSession(session);
 }
} 

设置断点,获取User对象。            

获取到了该对象,通过强制转换后得到了一个user对象。程序中添加了setName方法,也就是说会更新数据库中的名称,执行完成后检查数据库,如下图更新结果。     

1.2 load方法
功能类似于get方法,也是从数据库中获取数据并同步到对象中,该方法支持lazy是一种懒汉操作,它返回的是一个持久化的Object对象或者一个代理,所以需要进行转化。

public void testLoad1(){
 Session session=null;
 try{
  session=HibernateUtils.getSession();
  //不会马上查询语句,因为load支持lazy(延迟加载/懒加载)
  //什么教lazy?只有真正使用这个对象的时候,再创建,对于Hibernate来说
  //才真正发出查询语句,主要为了提高性能,lazy是Hibernate中非常重要的特性
  //Hibernate的lazy是如何实现的?采用代理对象实现,代理对象主要采用的是CGLIB库生成的
  //而不是JDK的动态代理,因为JDK的动态代理只能对实现了借口的类生成代理,CGLIB可以对类生成
  //代理,它采用的是继承方式
  User user=(User)session.load(User.class,"8a1b653745bcc7b50145bcc7b7140001");
  System.out.println(user.getName()); 

  //persistent状态
  //persistent状态的对象,当对象的属性发生改变的时候
  //Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
  user.setName("zhaoliu"); 

  session.getTransaction().commit();
 }catch(Exception e){
  e.printStackTrace();
 }finally{
  HibernateUtils.closeSession(session);
 }
} 

查询获取该User对象如下图:

分析上图,获取的User对象并不完整,或者说并没有常见一个User对象,更是一种代理,它使用了CGLIB来预加载对象,只有在使用该对象时才真正创建。
1.3 Get Vs load
get和load方法很重要,在面试Hibernate时经常会考到,下面对比下两者。
相同点:

(1)功能相同,将关系数据转化为对象;
(2)使用方法相同,同样需要制定两个参数
不同点:

(1)load方法支持lazy操作,预加载对象,在使用时才创建,get是直接将关系数据转化为对象;
(2)load加载对象如果不存在会抛出objectNotFoundException异常,get如果没有获取数据会返回null。

2、手动构造detached对象
想要获取对象还有另外一种方法,它区别于get与load方法,是一种手动获取的方法,首先常见一个对象,然后通过制定id的方式获取该对象的数据,方法如下:

public void testUer(){
  Session session=null;
  try{ 

    session=HibernateUtils.getSession();
    session.beginTransaction(); 

    //手动构造detached对象
    User user=new User();
    user.setId("8a1b653745bcc7b50145bcc7b7140001"); 

    //persistent状态
    //persistent状态的对象,当对象的属性发生改变的时候
    //Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
    session.getTransaction().commit();
  }catch(Exception e){
    e.printStackTrace();
  }finally{
    HibernateUtils.closeSession(session);
  }
} 

查看获取的结果图:

                    

分析结果图,代码中使用了setId方法为该对象制定了id号,在制定id号后就能够对该对象进行操作,在事务提交后同步到数据库中,采用了手动指定,手动指定了对象的信息。
2.1 Delete方法
删除数据库中指定的对象,在删除前必须将对象转化到Persistent状态,可以使用get、load或者手动的方法指定对象,使用方法如下代码:

session=HibernateUtils.getSession();
session.beginTransaction();
User user=(User)session.load(User.class,"8a1b653745bcc6d50145bcc6d67a0001");
//建议采用此种方式删除,先加载再删除
session.delete(user); 

2.2 Update

更新数据,该方法会修改数据库中的数据。在使用的时候会出现量中情况,更新数据库某个字段值或者更新数据库的整行值
2.2.1  更新某个字段值
如果只想要更新某个字段的值,在update前,需要使用load或者get方法使对象转化为persistent状态代码如下:

//获取session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
//或者可以使用另外的方法开启
//session.getTransaction().begin(); 

//加载获取User对象
//方法一:使用load方法
//User user=(User)session.load(User.class, "8a1b653745bcc7b50145bcc7b7140001");
//方法二:手动获取
User user=new User();
user.setId("8a1b653745bcc7b50145bcc7b7140001"); 

//更新姓名
user.setName("zhangsan");
session.update(user);
session.getTransaction().commit(); 

2.2.2 更新整行                       
想要更新整行的数据,可以采用手动将状态转换到detached状态,手动指定对象的id值,代码如下:

//获取session对象
session=HibernateUtils.getSession();
//开启事务
session.beginTransaction();
//或者可以使用另外的方法开启
//session.getTransaction().begin(); 

//手动获取
User user=new User();
user.setId("8a1b653745bcc7b50145bcc7b7140001"); 

//更新姓名
user.setName("zhangsan");
session.update(user);
session.getTransaction().commit(); 

查看更新结果:

分析更新结果,它其实更新了数据库的整行数据,这种更新操作有太多的不确定因素,不建议使用。

2.3 save方法

插入数据。在执行save方法时会调用数据库的insert语句,向数据库中添加新的一行。save后的对象会转化为持久态,在此状态下的对象能够再次更新对象,在最后提交事务时会同更改更新到数据库。如下:

public void testSave2(){
  Session session=null;
  Transaction tx = null;
  try{
    session=HibernateUtils.getSession();
    //开启事务
    tx= session.beginTransaction(); 

    //Transient状态
    User user=new User();
    user.setName("zhangsi");
    user.setPassword("123");
    user.setCreateTime(new Date());
    user.setExpireTime(new Date()); 

    //persistent状态
    //persistent状态的对象,当对象的属性发生改变的时候
    //Hibernate在清理缓存(脏数据检查)的时候,会和数据库同步
    session.save(user);
    user.setName("lisi"); 

    tx.commit(); 

  }catch(Exception e){
    e.printStackTrace();
    if(tx != null){
      tx.rollback();
    }
  }finally{
    HibernateUtils.closeSession(session);
  } 

  //detached状态
} 

查看上例运行结果视图:

分析结果:session在提交事务的时候其实做了两部的操作,结合代码中的更新过程,首先是新增了一个User对象,之后执行了save操作,它会调用insert语句,然后在代码中做了一个setName的操作,重新修改了名称,但这时还没有同步到数据库中而是在内存中,这时就会有两种状态,我们称此时的数据位脏数据,最后提交事务的时候更新到数据库中。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, hibernate
持久对象
hibernate持久化、hibernate持久化对象、hibernate数据持久化、hibernate持久层技术、hibernate持久化操作,以便于您获取更多的相关知识。

时间: 2024-12-02 01:42:22

深入解析Java的Hibernate框架中的持久对象_java的相关文章

在Hibernate框架中编写持久对象类实现外键关联的几点注意事项

关系数据库系统本身就比较复杂,加上Hibernate的O/R映射层,复杂度加重了,很容易出现问题,本人将最近遇到的问题和解决方法做一个总结,整理在下面的一系列文章中 正确理解Hibernate的聚合类型(collection)的使用 在Hibernate中正确实现关联关系中的级联操作(cascading) 在Hibernate框架中编写持久对象类实现外键关联的几点注意事项 本文是第三篇,讲解在one-to-many(一对多)关联关系中的对象类的几个关键方法的实现.主要是equals(),hash

深入解析Java的Hibernate框架中的一对一关联映射_java

作为一个ORM框架,hibernate肯定也需要满足我们实现表与表之间进行关联的需要.hibernate在关联方法的实现很简单.下面我们先来看看一对一的做法:  不多说了,我们直接上代码:  两个实体类,TUser和TPassport: public class TUser implements Serializable{ private static final long serialVersionUID = 1L; private int id; private int age; priva

简要分析Java的Hibernate框架中的自定义类型_java

最近看到hibernate的自定义类型,这个以前没接触过,在这里记录一下,当是对自己知识的巩固,也让没有接触过的朋友一起学习研究一番.  1)自定义类型,顾名思义,当然就是由于内部的类型不满足需求,而自己来进行实现的类型.这种情况不多,但我们还是有必要学习一下,技多不压身嘛.也学习一下,别人在做框架的时候是怎么去考虑的,怎么去思考扩展性的.  自定义类型有两个方法来实现,一种是实现UserType,另外一种实现CompositeUserType,另外可能还有一些方法,但我暂时没用到,先不讲了.

解析Java的Hibernate框架中的持久化类和映射文件_java

持久化类Hibernate的整个概念是采取从Java类属性的值,并将持久到数据库表.一个映射文件Hibernate的帮助确定如何从拉动类的值,并将它们映射与表和相关的域. 其对象或实例将存储在数据库表中的Java类在Hibernate中称为持久化类. Hibernate的效果最好,如果这些类遵循一些简单的规则,也称为普通Java对象(POJO)编程模型.有下列持久化类的主要规则,但是,这些规则并不是必需的. 将所有的持久化Java类需要一个默认的构造函数. 所有类应该包含为了让容易识别对象内Hi

详解Java的Hibernate框架中的Interceptor和Collection_java

Interceptor讲到Interceptor,相信熟悉struts2的童鞋肯定不会陌生了,struts2可以自定义拦截器进行自己想要的一系列相关的工作.而这里我们说的Interceptor也是差不多相似的功能.  废话不说,直接来代码:  下面这个是MyInterceptor类,它实现了Interceptor接口: public String onPrepareStatement(String arg0) { return arg0; } public boolean onSave(Obje

Java的Hibernate框架中Criteria查询使用的实例讲解_java

我们讲一下Criteria查询,这个对于不是太熟悉SQL语句的我们这些程序员来说是很容易上手的.  废话不多说,看一下例子:  实体类如下: public class User implements Serializable{ private static final long serialVersionUID = 1L; public Long id; private String name; private int age; //省略Get/Set方法 }   映射文件我们就不写了,很简单的

Java的Hibernate框架中用于操作数据库的HQL语句讲解_java

 上次我们一起学习了用Criteria进行相关的操作,但由于Criteria并不是Hibernate官方推荐的查询方式,我们也并不多用.现在我们来看一下官方推荐的HQL,一起学习一下它的强大.  说是HQL,也就是Hibernate查询语句,和SQL有什么区别呢?一个字母的区别,哈哈.  当然不是这样,HQL和SQL的区别在于思想的不同,HQL是用面向对象的方向进行查询,而SQL则是对数据库二维表进行查询,这里包含的是思想的不同.HQL实际上也是SQL,它由Hibernate帮我们在内部进行转换

详解Java的Hibernate框架中的注解与缓存_java

注解Hibernate注解是一个没有使用XML文件来定义映射的最新方法.可以在除或替换的XML映射元数据使用注解. Hibernate的注解是强大的方式来提供元数据对象和关系表的映射.所有的元数据被杵到一起的代码POJO java文件这可以帮助用户在开发过程中同时要了解表的结构和POJO. 如果打算让应用程序移植到其他EJB3规范的ORM应用程序,必须使用注解来表示映射信息,但仍然如果想要更大的灵活性,那么应该使用基于XML的映射去. 环境设置Hibernate注释 首先,必须确保使用的是JDK

详解Java的Hibernate框架中的缓存与原生SQL语句的使用_java

Hibernate缓存缓存是所有关于应用程序的性能优化和它位于应用程序和数据库之间,以避免数据库访问多次,让性能关键型应用程序有更好的表现. 缓存对Hibernate很重要,它采用了多级缓存方案下文所述: 第一级缓存: 第一级缓存是Session的缓存,是一个强制性的缓存,通过它所有的请求都必须通过. Session对象不断自身的动力的对象,提交到数据库之前. 如果发出多个更新一个对象,Hibernate试图拖延尽可能长的时间做了更新,以减少发出的更新SQL语句的数量.如果您关闭会话,所有被缓存