`
forever1121
  • 浏览: 16431 次
  • 性别: Icon_minigender_2
  • 来自: 齐齐哈尔
社区版块
存档分类
最新评论

Hibernate_4

阅读更多
当程序通过Hibernate来加载、保存、更新或删除对象时,会触发以下组件做出相应的处理:在数据库层,会引发触发器执行相关的操作;在Hibernate层,可以触发拦截器执行相关操作;在Hibernate层,可以触发事件处理系统执行相关操作。

能激发触发器运行的事件可以分为以下几种:插入记录事件,即执行insert语句;更新记录事件,即执行update语句;删除记录事件,即执行delete语句。

Session的save()、update()、saveOrUpdate()或delete()方法都会激发一个触发器,而这个触发器的行为会导致session的缓存的数据与数据库不一致,解决的办法是在执行完这个操作后,立即调用session的flush()个refresh()方法,迫使session的缓存与数据库同步。

不管游离的对象的属性是否发生过变化,都会执行update语句,而update语句会激发数据库中相应的触发器。因此应该在映射文件的<class>元素中设置select-before-update属性,使它为true,这样不会盲目执行update语句。

数据库触发器经常用来生成审计日志,缺点是不支持跨数据平台。Hibernate的拦截器也能生成审计日志,不依赖于具体的数据库平台。可以把拦截器看作是持久化层的触发器,当session执行save()、update()、saveOrUpdate()、delete()和refresh()方法时,就会调用拦截器的相关方法。用户定义的拦截器必须要实现org.hibernate.Interceptor接口,在这个接口中主要定义了如下方法:
findDirty():决定session缓存中哪些对象是脏对戏,session的flush()方法调用根本方法,若返回null,session会按默认的方式进行脏检查。
instantiate(Class clazz,Serializable id):创建实体类的实例。在session构造实体类的实例前调用本方法。若返回null,session会按默认的方式创建实体类的实例。
isUnsaved(Object entity):session的saveOrUpdate()方法调用本方法;若返回true,则调用save()方法,若返回false,则调用update()方法;若返回null,就按默认的方式决定参数entity是临时对象还是游离对象。
onDelete():当session删除一个对象之前调用此方法。
onFlushDirty():当session的flush()方法执行玩所有SQL语句后调用次方法。
onLoad():当session初始化一个持久化对象时调用本方法,若在这个方法中修改了持久化对象的数据,就返回true,否则返回false。
onSave():当session保存一个对象之前调用本方法,若在这个方法中修改了持久化对象的数据,就返回true,否则返回false。
postFlush(Iterator entities):当session的flush()方法执行完所有SQL语句后调用此方法。
preFlush(Iterator entities):当session执行的flush()方法之前调用此方法。

在org.hibernate包中还提供了Interceptor接口的一个实现类EmptyInterceptor。这个类的所有方法实际上什么也不做,用户自定义的拦截器类也可以扩展EmptyInterceptor类。

审计系统主要包括一下接口和类:
Auditable:凡是需要审计的持久化类都应该所实现Auditable接口。
AuditLogRecord类:代表具体的审计日志。
AuditLogInterceptor类:代表用于生成审计日志的拦截器。
AuditLog类:提供用于生成审计日志的静态方法logEvent()。

public interface Auditable{
   public Long getId;();
}

public class AuditLogRecord{
   public String message;
   public Long entityId;
   public Class entityClass;
   public Date created;
  
   public AuditLogRecord(String message,Long entityId,Class entityClass){
       this.message = message ;
       this.entityId = entityId ;
       this.entityClass = entityClass ;
       this.created = new Date() ;
   }
   public AuditLogRecord(){}
}

<hibernate-mapping>
   <class name="AuditLogRecord"  table="AUDIT_LOGS">
       <id type="long" column="ID">
           <generator class="native"  />
       </id>
       <property name="message" column="MESSAGE" access="field"  />
       ...
</hibernate-mapping>

为了使session保存或更新对象,能够激发拦截器,必须使interceptor与session关联。Interceptor对象有两种存放方式:
SessionFactory.openSession(Interceptor):为每个session实例分配一个interceptor实例,这个实例存放在session范围内。
Configuration.setInterceptor(Interceptor):为SessionFactory实例分配一个interceptor实例,这个实例存放在SessionFactory范围内,被所有的Session实例共享。

Hibernate3的核心处理模块采用了“事件/监听器”设计模式。

public Object get(String entityName, Serializable id) throws HibernateException{
   LoadEvent event = new LoadEvent(id, entityName, false, this) ;
   boolean success = false ;
   try{
      fileLoad(event, LoadEventListener.GET) ;
      success = true ;
      return event.getResult() ;
   }finally{
      afterOperation(success);
   }
}
Session的get()方法触发org.hibernate.event.LoadEvent事件,该事件由org.hibernate.event.LoadEventListener接口的实现类来处理。

在org.hibernate.event包中提供了各个监听器接口的默认实现类。此外,org.hibernate.event.def包中提供了各个监听器接口的默认实现类。

批量处理数据是指在一个事务中处理大量数据。一般来说,应避免在应用层进行批量操作,而应该在数据层直接进行批量操作。

在应用层主要有一下4种方式进行批量操作:
通过Session来进行批量操作;通过StatelessSession来进行批量操作;通过HQL来进行批量操作;直接通过JDBC API进行批量操作。

若通过一个session对象来出库大量持久化对象,应该及时从缓存中清空已经处理完毕并且不会在访问的对象。具体做法是在处理完一个对象或小批对象后,立刻调用flush()清理缓存,然后调用clear()清空缓存。

通过session来进行批量处理会受到一下约束:需要在Hibernate的配置文件中设置JDBC单次批处理的数目,合理的取值通常为10~50;若对象采用identity标识符生成器,则Hibernate无法在JDBC层进行批量插入操作;进行批量处理时,建议关闭Hibernate的第二级缓存。

批量插入:
Session session = sessionFactory.openSession() ;
Transaction tx = session.beginTransaction() ;
for(int i = 0 ; i < 10000 ; i++ ){
    XX xx = new XX() ;
    session.save(xx) ;
    if( i % 20 == 0 ){
         session.flush() ;
         session.clear() ;
    }
}
tx.commit();
session.close();

批量更新:使用可滚动的结果集org.hibernate.ScrollableResults,Query的scroll()方法返回一个ScrollableResults对象。
Session session = sessionFactory.openSession() ;
Transaction tx = session.beginTransaction() ;
ScrollableResults xx = session.createQuery("from XX").scroll(ScrollMode.FORWARD_ONLY) ;
int count = 0 ;
while( xx.next() ){
    XX xx = (XX) xx.get(0) ;
    xx.setXXX(abc);
        if( i % 20 == 0 ){
         session.flush() ;
         session.clear() ;
    }
}
tx.commit();
session.close();
Query的scroll()方法返回的ScrollableResults对象中实际并不包含任何对象,它仅包含用于在线定位数据库中对象表记录的游标。

Session具有一个用于保持内存中对象与数据库中相应数据保持同步的缓存,位于Session缓存中的对象为持久化对象。但在进行批量操作时,把大量对象存放在Session缓存中会消耗大量内存空间。作为一种替代方案,可采用无状态的StatelessSession来进行批量处理。
通过StatelessSession进行批量更新:
SatelessSession session = sessionFactory.openStatelessSession() ;
Transaction tx = session.beginTransaction() ;
ScrollableResults xx = session.createQuery("from XX").scroll(ScrollMode.FORWARD_ONLY) ;
int count = 0 ;
while( xx.next() ){
    XX xx = (XX) xx.get(0) ;
    xx.setXXX(abc);
        if( i % 20 == 0 ){
         session.flush() ;
         session.clear() ;
    }
}
tx.commit();
session.close();

StatelessSession和Session有以下区别:
StatelessSession没有缓存。通过StatelessSession来加载、保存或更新后的对象都处于游离状态。
StatelessSession不会与Hibernate的第二级缓存交互。
当调用StatelessSession的save()、update()或delete()方法时,会立即执行相应的SQL,而不会执行一条语句。
StatelessSession不会对所加载的对象自动进行脏检查。
StatelessSession不会对关联的对象进行任何级联操作。
StatelessSession所做的操作可以被Interceptor拦截器捕获到,但会被Hibernate的事件处理系统忽略。
通过一个StatelessSession对象两次加载OID为1的对象时,会得到两个不同的内存地址的对象。

利用HQL进行批量操作:直接在数据库中完成,不会占用内存空间
Session session = sessionFactory.openSession() ;
Transaction tx = session.beginTransaction() ;
String hql = "update X x set x.xx =: newXx where x.yy = : oldYy" ;
int hqlEntities = session.createQuery(hql).setStrng("a","b")
                                          .setStrng("c","d")
                                          .executeUpdate();
tx.commit();
session.close();
                                 
Hibernate需要通过对象-关系映射文件中的元数据来了解域模型中的持久化类及其属性的类型。Hibernate提供了ClassMetadata和CollectionMetaData这两个接口来访问元数据。这两个接口位于org.hibernate.metadata中。SessionFactory的getClassMetadata()和getCollectionMeta()方法分别返回这两个接口的实例。
X x = new X();
ClassMetadata xMeta = sessionFactory.getClassMetaData(X.class);
Object[] propertyValues = xMeta.getPropertyValues(x);
String[] propertyNames = xMeta.getPropertyNames();
Type[] propertyTypes = xMeta.getPropertyTypes();

聚集关系:在域模型中,有些类由几个部分类组成,部分类的对象的生命周期依赖于整理类对象的生命周期,当整体消失时,部分也随之小时。这种整体与部分的关系被称为聚集关系。
<component name=""  class="">
  <parent name="" />
  <property name=""  type="" column=""  />
  ...
</component>
<component>元素表明该属性是类的父类的一个部分。

值类(value)和实体类(entity)的区别:值类型没有OID,并不能被单独的实体化,它的生命周期依赖于所属的持久化类的对象的生命周期。实体类型有OID,可以被单独持久化。
分享到:
评论

相关推荐

    一个简单的hibernate_4 链接Oracle例子

    【标题】:“一个简单的hibernate_4 链接Oracle例子” 在Java开发中,Hibernate是一个非常流行的Object-Relational Mapping(ORM)框架,它允许开发者以面向对象的方式处理数据库操作,极大地简化了数据库编程。这...

    hibernate_day02笔记

    4. 为了确保数据的完整性和避免歧义,建议使用包装类而非基本类型。例如,分数属性可以使用Integer而非int,因为null值可以表示未参加考试。 **Hibernate主键生成策略**: 1. Hibernate提供了多种主键生成策略,如...

    hibernate_day03笔记

    hibernate_day03笔记

    hibernate_cache_level_1

    在Java世界中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者用面向对象的方式处理数据库操作。在大型应用中,为了提高性能,有效地管理数据访问,Hibernate引入了缓存机制。本篇文章将深入探讨...

    Hibernate_Tools_for_Eclipse插件的安装和使用

    4. 在 Eclipse 目录下建立 links 文件夹,并在 links 文件夹下建立 hibernatetools.link 文件,输入 Hibernatetools 的绝对目录。 5. 重新启动 Eclipse,即可看到 Hibernate_Tools_for_Eclipse 插件已经安装完成。 ...

    hibernate_day04笔记

    hibernate_day04笔记

    DMS.rar_dms_hibernate_myeclipse hibernate_mysql hibernate_struts

    4. **Struts**:Struts是Apache软件基金会的开源MVC(模型-视图-控制器)框架,用于构建基于J2EE的Web应用。它帮助开发者组织和控制应用的业务逻辑,分离显示层和控制层,使得代码更易于维护。在这个项目中,Struts...

    hibernate_day4_hibernate_sick7s3_

    【标题】"hibernate_day4_hibernate_sick7s3_" 暗示这是一个关于Hibernate框架的学习资源,可能是第四天的学习内容,专注于"hibernate_sick7s3"这个特定主题。在这个主题下,可能涉及了更深入或者特别的使用场景或...

    Hibernate_QBC和Hibernate_QBE

    标题"Hibernate_QBC和Hibernate_QBE"提及了两个关于Hibernate的查询方式,即Query By Criteria(QBC)和Query By Example(QBE)。Hibernate是Java领域中一个广泛使用的对象关系映射(ORM)框架,它允许开发者以面向...

    java_hibernate_day01.pdf

    java_hibernate_day01.pdf

    java_hibernate_day02.pdf

    java_hibernate_day02.pdf

    Hibernate_3.2.0_Reference_zh_CN.rar hibernate中文api

    4. **主键(Primary Key)**:`@Id`注解用于标识类中的主键字段,`@GeneratedValue`可设置主键生成策略,如自动增长、序列等。 5. **持久化类(Persistent Class)**:通过Hibernate注解或XML映射文件,将Java类...

    hibernate_second2项目源码

    4. **性能考虑**:虽然级联操作方便,但如果不小心可能会导致大量的数据库操作,影响性能。因此,在实际使用中,需要根据业务需求谨慎选择级联类型,并合理控制级联范围。 在`hibernate_second2`项目中,我们可以...

    struts_hibernate_bbs.rar_bbs_hibernate b_hibernate bbs_struts hi

    Struts和Hibernate是Java开发中两个非常重要的框架,它们在构建Web应用程序,特别是大型的、数据驱动的BBS(Bulletin Board System,论坛)系统时,起到了核心作用。本压缩包"struts_hibernate_bbs.rar"包含了一个...

    Hibernate_3.2.0_Reference_zh_CN

    4. **查询语言(HQL)**:Hibernate特有的查询语言,类似于SQL,但面向对象,允许开发者以类和对象的方式进行查询,支持复杂的查询条件和关联操作。 5. ** Criteria API**:提供了一种更加面向对象的查询方式,可以...

    test_hibernate_oracle_03.zip_Insert _hibernate_oracle_query_upda

    4. **Query**:在Hibernate中,可以通过HQL(Hibernate查询语言)或Criteria API进行数据查询,这两种方式都比直接写SQL更具有面向对象的特点。 5. **Update**:更新数据库记录也是Hibernate的重要功能,通过调用...

    MyEclipse_Hibernate_Quickstart

    4. **支持的数据库服务器**:由于本教程涉及Hibernate的使用,因此需要选择一个被Hibernate和MyEclipse Database Explorer支持的数据库。这些数据库包括但不限于: - Axion - HypersonicDB - InstantDB - ...

    JavaEE源代码 Hibernate_Spring

    JavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_SpringJavaEE源代码 Hibernate_...

    JavaEE源代码 Hibernate_mapping

    JavaEE源代码 Hibernate_mappingJavaEE源代码 Hibernate_mappingJavaEE源代码 Hibernate_mappingJavaEE源代码 Hibernate_mappingJavaEE源代码 Hibernate_mappingJavaEE源代码 Hibernate_mappingJavaEE源代码 ...

Global site tag (gtag.js) - Google Analytics