Hibernate框架核心组件

Hibernate框架简述 中,演示了一个简单的Hibernate应用,但并没有深入说明其中程序,在这篇中将比较详细的介绍一下Hibernate的核心组件。
首先最关键一点就是Hibernate的配置文件,如果仔细看过我前面的笔记构建一个简单的基于MVC模式的JavaWeb ,我们可以大概知道hibernate的配置文件就相当于构建一个简单的基于MVC模式的JavaWeb 一文中的db.properties文件,当时我们在db.properties文件中设置了连接数据库的参数,因此Hibernate的配置文件作用也是如此,但它还有一个作用是要定义程序中我们用到的映射文件(***.hbm.xml)。
例:

hibernate.cfg.xml
<? xml version='1.0' encoding='GBK' ?>
<! 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 ="connection.username" > root </ property >
    
< property  name ="connection.url" >
        jdbc:mysql://localhost:3306/study
    
</ property >
    
< property  name ="dialect" >
        org.hibernate.dialect.MySQLDialect
<!--  这里是MySQL的Dialect  -->
    
</ property >
    
< property  name ="myeclipse.connection.profile" > MySQL5.0 </ property >
    
< property  name ="connection.password" > root </ property >
    
< property  name ="connection.driver_class" >
        org.gjt.mm.mysql.Driver
<!--  这里是MySQL的JDBC driver class名  -->
    
</ property >
    
< property  name ="show_sql" > true </ property > <!--  向控制台输出SQL语句  -->
    
    
    
< mapping  resource ="hibernate/PO/TRegister.hbm.xml"   /> <!--  指定要用到的映射文件  -->

</ session-factory >

</ hibernate-configuration >

另外它的持久化类其实就是一个普通的JavaBean,只不过一个持久化类对应 一个数据表。另外定义的时候 要遵循一定的规则!
映射文件是把一个持久化类与一张表映射起来。
例:

hibernate映射文件
<? xml version="1.0" encoding="GBK" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    映射文件
-->
< hibernate-mapping >
    
< class  name ="hibernate.PO.TRegister"  table ="t_register" >
        
< id  name ="id"  type ="java.lang.Integer" >
            
< column  name ="id"   />
            
<!--  我在MYSQL中并没有设置该字段递增,但在Hibernate中依然可以设置为递增  -->
            
< generator  class ="increment"   />
        
</ id >
        
< property  name ="userName"  type ="java.lang.String" >
            
< column  name ="userName"  length ="30"   />
        
</ property >
        
< property  name ="userPwd"  type ="java.lang.String" >
            
< column  name ="userPwd"  length ="30"   />
        
</ property >
        
< property  name ="sex"  type ="java.lang.String" >
            
< column  name ="sex"  length ="10"   />
        
</ property >
        
< property  name ="age"  type ="java.lang.Integer" >
            
< column  name ="age"   />
        
</ property >
    
</ class >
</ hibernate-mapping >

说明:
class元素
 用来定义一个持久化类,它的属性name和table分别为持久化的类名及对应到DB中的表名。
 id元素
   是class的子元素。被映射的类必须声明对应数据表主键字段。大多数据有一个JavaBean 风格的属性,为一个实例包含惟一的标识。id元素定义了该属性到数据表主键字段的映射。它有name,type和column三个属性和一个generator子元素
  generator 元素 用来指定id标识的生成类的名字。它有一个属性class,用来指定一个Java类名。 该类用来为持久化类的实例生成惟一的标识。所以也叫生成器 (generator)。如 果这个生成器实例需要某些配置值或者初始化参数,可用<param>元素来传递。

 所有生成器都实现org.hibernate.id.IdentifierGenerator接口。
Hibernate提供了很多内置的生成器。下面是Hibernate内置生成器的快捷名字:
   1:increment(递增)。 其为org.hibernate.id.IncrementGenerator类快 捷名字,用于为long,short或者int类型生成惟一标记。只有在没有其他进程往 同一张表中插入数据时才能使用。在集群下不要使用。
   2:identity(标识)。 其为org.hibernate.id.IdentityGenerator类快捷 名字,对DB2,MySQL,SQL Server和Sybase等数据库的内置标识字段提供支持。 返回的标识符是long,short或者int类型的。
   3:sequence(序列)。 其为org.hibernate.id.SequenceGenerator类的快 捷名字,为DB2,Oracle和SAP DB等数据闸的内置序列提供支持。返回类型是long, short或者int类型的。
   4:seqhilo(序列高/低位)。 org.hibernate.id.SequenceHiLoGenerator 类的快捷名字,使用一个高/低位算法来高效地生成long,short或者int类型的标识符, 需要指定一个数据库sequence的名字。
   5:uuid.hex。 其 为org.hibernate.id.UUIDHexGenerator类的快捷名字,使用 一个128位的UUID算法生成字符串类型的标识符,在一个 网络中是惟一的(使用了IP地 址)。UUID被编码为一个32位16进制的字符串,包含IP地址,JVM的启动时间(精确到 14s),系统时间和一个 计算器值(在JVM中是惟一的)。
   6:assigned。 其为org.hibernate.id.Assigned类的快捷名字,可让应用程序在
   执行save()方法之前为对象分配一个标识符。如果需要 为应用程序分配一个标识符(而 非由Hibernate来生成它们),可以用assigned生成器。
   7:foreign。 其为org.hibernate.id.ForeignGenerator类的快捷名字。它使用了另外一个相关的对象标识符,和<one-to-one>元素一起使用。
 property元素:
  是class元素的一个子元素。它为类声明一个持久化的,JavaBean网络的属性。它有 name,colum,type和length等属性。

Configuration类
它负责管理Hiberante的配置信息,它主要用来加载这些配置文件。如上术的hibernate.cfg.xml文件!
例:

// 加载Hibernate的配置文件
            Configuration config  =   new  Configuration().configure( " /hibernate/hibernate.cfg.xml " );
            
// 还可以加载映射文件
            Configuration config  =   new  Configuration().addFile( " TRegister.hbm.xml " ); // 方法一
            Configuration config  =   new  Configuration().addClass(hibernate.PO.TRegister. class ); // 方法二
            Configuration config  =   new  Configuration().addURL(Configuration. class .getResource( " TRegister.hbm.xml " )); // 方法三
            

SessionFactory接口
SessionFactory负责Session实例的创建。可以通过Configuration实例创建
例:

Configuration config  =   new  Configuration().configure( " /hibernate/hibernate.cfg.xml " );
    
SessionFactory    sessionFactory 
=  config.buildSessionFactory();


Congifuration对象会根据当前的配置信息,生成SessionFactory对象。SessionFactory对象一旦构造完毕, 即被赋予特定的配置信息,即以后配置改变不会影响到创建的SessionFactory对象。如果要把屐后的配置信息赋给SessionFactory对 象,需要从新的Configuration对象生成拳的SessionFactory对象。
SessionFactory是纯种安全的,可以被多线程调用以取得Session,而且构造SessionFactory很消耗资源,所以多数 情况下一个应用中只初始化一个SessionFactory,为不同的线程提供Session。
当客户端发送一个请求线程时,SessionFactory生成一个Session对象来处理客户请求,如下:

     public   static   final  ThreadLocal session  =   new  ThreadLocal();
    
    
public   static  Session currentSession()  throws  HibernateException
    
{
        Session s 
=  (Session)session.get();
        
// Open a new Session,if this Thread has none yet
        
// 如果此线程还没有打开一个Session,则新建一个
         if (s  ==   null   ||   ! s.isOpen())
        
{
            s 
=  sessionFactory.openSession();
            session.set(s);
        }

        
return  s;
    }


Session接口
Session是应用程序与数据库之间的一个会话,是Hibernate运作的中心,持久层操作的基础,相当于JDBC中的Connection。Session对象是通过SessionFactory创建的:
         Session      session = SessionFactory.openSession();
一 个持久化类与普通的JavaBean没有任何区别,但是它与Session关联后,就具有了持久化能力。当然,这种持久化操作是受Session控制的, 即通过Session对象的装载,保存,创建或查询持久化对象。Session类的save(),delete()和load()等方法,来分别完成对持 久化对象的保存,删除,修改加载等操作!Session类方法的用途可以分以下五类:
1:取得持久化对象:get()和load()等方法。
2:持久化对象的保存,更新和删除:save(),update()saveOrUpdate()和delete()等方法。
3:createQuery()方法:用来从Session生成的Query对象。
4:beginTransaction()方法:从Session对象生成一个Transaction对象。
5: 管理Session的方法:isOpen(),flush(),clear(),evict()和close()等方法,其中isOpen()方法用来检 查Session是否仍然打开;flush()用来清理Session缓存,并把缓存中的SQL语句发送出去,clear()用来清除Session中的 所有缓存对象evict()方法来清楚Session缓存中的某个对象;close()关闭Session。
取得持久化对象的方法
取得持久化对象的方法主要有get()和load(),它们通过主键id来取得PO。
get()方法示例

public   void  getDemo()
    
{
        Session session 
=  HibernateUtil.currentSession(); // 生成Session实例
        TRegister tr  =  (TRegister)session.get(TRegister. class new  Integer( 1 ));
        
        System.out.print(tr.getUserName());
        
/** */ /**
         * get()方法的执行顺序如下:
         * a):首先通过id在session缓存中查找对象,如果存在此id的对象,直接将其返回
         * b):在二级缓存中查找,找到后将 其返回。
         * c):如果在session缓存和二级缓存中都找不到此对象,则从数据库中加载有此ID的对象
         * 因此get()方法并不总是导致SQL语句,只有缓存中无此数据时,才向数据库发送SQL!         
         
*/

    }


load()方法示例

public   void  loadDemo()
    
{
        Session session 
=  HibernateUtil.currentSession();
        TRegister tr 
=  (TRegister)session.load(TRegister. class new  Integer( 1 ));
        System.out.println(tr.getUserName());
        
/** */ /**
         * 与get()的区别:
         * 1:在立即加载对象(当hibernate在从数据库中取得数据组装好一个对象后
         * 会立即再从数据库取得数据此对象所关联的对象)时,如果对象存在,
         * load()和get()方法没有区别,都可以取得已初始化的对象;但如果当对
         * 象不存在且是立即加载时,使用get()方法则返回null,而使用load()则
         * 抛出一个异常。因此使用load()方法时,要确认查询的主键ID一定是存在
         * 的,从这一点讲它没有get方便!
         * 2:在延迟加载对象(Hibernate从数据库中取得数据组装好一个对象后,
         * 不会立即再从数据库取得数据组装此对象所关联的对象,而是等到需要时,
         * 都会从数据库取得数据组装此对象关联的对象)时,get()方法仍然使用
         * 立即加载的方式发送SQL语句,并得到已初始化的对象,而load()方法则
         * 根本不发送SQL语句,它返回一个代理对象,直到这个对象被访问时才被
         * 初始化。
         
*/

    }

持久化对象的保存,更新和删除方法
save()方法
session的save()方法将 一个PO的属性取出放入PreparedStatement语句中,然后向数据库中插入一条记录(或多条记录,如果有级联)。
session保存一个对象时,按如下步骤进行:
1:根本配置文件为主键id设置的生成算法 ,为PO指定 一个ID。
2:将 PO对象纳入session内部缓存(一个Map)内。
3:事务提交时,清理缓存,将 新对象通过insert语句持久化到数据库中。
如果要为新的PO强制指定一个ID,可以调用Session的重载方法save(Object obj,Serializable id)
例:
       session.save(tRegister, new Integer(123));
在调用save()方法时,并不立即执行SQL语句,而是等到清理完毕缓存时才执行。如果在调用save()方法后又修改了PO的属性,则Hibernate将 会发送一条insert语句和一条update语句来完成持久化操作,如下:

     public   void  saveDemo()
    
{
        TRegister tr 
=   new  TRegister();
        tr.setId(
1111 ); // 为对象设定一个ID,但注意此ID是无效的,因为我们在配置文件中ID设置为Increment,这样将被Hibernate的increment算法生成的值覆盖
        tr.setAge( 23 );
        tr.setSex(
" " );
        tr.setUserName(
" evoll " );
        tr.setUserPwd(
" efly " );
        
        Session session 
=  HibernateUtil.currentSession();
        Transaction tx 
=  session.beginTransaction();
        session.save(tr);
        tr.setUserName(
" xuanflt " ); // 在save后又修改了PO名字
        tx.commit();
    }

监视上述程序运行会产生二条SQL:
Hibernate: select max(id) from t_register
Hibernate: insert into t_register (userName, userPwd, sex, age, id) values (?, ?, ?, ?, ?)
Hibernate: update t_register set userName=?, userPwd=?, sex=?, age=? where id=?
因此,最好是在对象状态稳定时再调用 save()方法,可以少执行一条update语句。
调用save()方法将临时对象保存到数据库中,对象的临时状态将 变为持久化状态。当对象在持久化状态时,它一直位于Session缓存中,对它的任何操作在事物提交时都将同步保存到数据库中 ,因此,对一个已经持久化的对象调用save()或update()方法是没有意义的 ,如下:

     public   void  saveDemo()
    
{
        TRegister tr 
=   new  TRegister();
        tr.setId(
1111 ); // 为对象设定一个ID,但注意此ID是无效的,因为我们在配置文件中ID设置为Increment,这样将被Hibernate的increment算法生成的值覆盖
        tr.setAge( 23 );
        tr.setSex(
" " );
        tr.setUserName(
" evoll " );
        tr.setUserPwd(
" efly " );
        
        Session session 
=  HibernateUtil.currentSession();
        Transaction tx 
=  session.beginTransaction();
        session.save(tr);
        tr.setUserName(
" xuanflt " ); // 在save后又修改了PO名字
        session.save(tr);     // 无效
        session.update(tr);     // 无效
        tx.commit();     // 提交事物
    }

程序运行效果还是和上面的一样!
update()方法
Session的update()方法是用来更新脱管对象的。它的用法如下:

public   void  updateDemo()
    
{
        TRegister tr 
=   new  TRegister();
        Session session 
=  HibernateUtil.currentSession();
        Transaction tx 
=  session.beginTransaction();
        tr 
=  (TRegister)session.get(TRegister. class new  Integer( 1 ));
        tr.setUserName(
" updated " ); // 更新脱管对象
        tx.commit();
    }

调用update()方法时,并不是立即发送SQL语句,对对象的更新操作将积累起来,在事物提交时由flush()清理缓存,然后发送一条SQL语句完成全部的更新操作!
saveOrUpdate()方法
在实际应用中WEB程序员自言自语不会注意一个对象是脱管对象还是临时对象,而对脱管对象使用save()方法是不对的,对临时对象使用update()方法也是不对的。为了解决这个问题,便产生saveOrUpdate()方法。
saveOrUpdate()方法首先会判断该PO是脱管对象还是临时对象,然后会调用合适的方法。
那么saveOrUpdate()方法如何判断PO是临时对象还是 脱管对象呢?当满足下载情况之一时,Hibernate就认定它是临时对象。
1:在映射表中为<id>设元素设置了unsaved-valu属性,并且实体对象的ID取值和unsaved-value匹配(默认为null)(注意:int和long型的ID的unsaved-value默认值为0)。
2:在映射文件中为<version>元素设置了unsaved-value属性,并且实体对象的version取值和unsaved-value匹配(默认为null)。
delete()方法
session类的delete()方法负责删除一个对象(包括持久对象和脱管对象),以下为删除一个持久对象的示例!

     public   void  deleteDemo()
    
{
        TRegister tr 
=   new  TRegister();
        Session session 
=  HibernateUtil.currentSession();
        Transaction tx 
=  session.beginTransaction();
        tr 
=  (TRegister)session.get(TRegister. class new  Integer( 3 ));
        session.delete(tr);
// 删除持久对象
        tx.commit();
    }

监视运行:
Hibernate: select tregister0_.id as id0_0_, tregister0_.userName as userName0_0_, tregister0_.userPwd as userPwd0_0_, tregister0_.sex as sex0_0_, tregister0_.age as age0_0_ from t_register tregister0_ where tregister0_.id=?
Hibernate: delete from t_register where id=?

     public   void  deleteDemo2()
    
html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值