`
gao_20022002
  • 浏览: 164795 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Hibernate整理学习之基础概念2

阅读更多

Hibernate是完整的对象/关系映射解决方案,它提供了对象状态管理(state management)的功能,使开发者不再需要理会底层数据库系统的细节。 也就是说,相对于常见的JDBC/SQL持久层方案中需要管理SQL语句,Hibernate采用了更自然的面向对象的视角来持久化Java应用中的数据。
使用Hibernate的开发者应该总是关注对象的状态(state),不必考虑SQL语句的执行。 而对于SQL语句,只有开发者在进行系统性能调优的时候才需要进行了解。
Hibernate定义并支持的对象状态(state): 瞬时(Transient) 、持久(Persistent)、脱管(Detached) 。
瞬时(Transient) - 由new操作符创建,且尚未与Hibernate Session 关联的对象被认定为瞬时(Transient)的。瞬时(Transient)对象不会被持久化到数据库中,也不会被赋予持久化标识(identifier)。 如果瞬时(Transient)对象在程序中没有被引用,它会被垃圾回收器(garbage collector)销毁。 使用Hibernate Session可以将其变为持久(Persistent)状态。(Hibernate会自动执行必要的SQL语句)
持久(Persistent) - 持久(Persistent)的实例在数据库中有对应的记录,并拥有一个持久化标识(identifier)。 持久(Persistent)的实例可能是刚被保存的,或刚被加载的,无论哪一种,按定义,它存在于相关联的Session作用范围内。 Hibernate会检测到处于持久(Persistent)状态的对象的任何改动,在当前操作单元(unit of work)执行完毕时将对象数据(state)与数据库同步(synchronize)。 开发者不需要手动执行UPDATE。将对象从持久(Persistent)状态变成瞬时(Transient)状态同样也不需要手动执行DELETE语句。
脱管(Detached) - 与持久(Persistent)对象关联的Session被关闭后,对象就变为脱管(Detached)的。 对脱管(Detached)对象的引用依然有效,对象可继续被修改。脱管(Detached)对象如果重新关联到某个新的Session上, 会再次转变为持久(Persistent)的(在Detached其间的改动将被持久化到数据库)。 这个功能使得一种编程模型,即中间会给用户思考时间(user think-time)的长时间运行的操作单元(unit of work)的编程模型成为可能。 我们称之为应用程序事务,即从用户观点看是一个操作单元(unit of work)。
Hibernate认为持久化类(persistent class)新实例化的对象是瞬时(Transient)的。 我们可通过将瞬时(Transient)对象与session关联而把它变为持久(Persistent)的。
持久化标识(identifier):可以认为主键。
使用Hibernate的 传播性持久化(transitive persistence)功能自动保存相关联那些对象。 这样连违反NOT NULL约束的情况都不会出现了 - Hibernate会管好所有的事情。

装载对象:如果你知道某个实例的持久化标识(identifier),你就可以使用Session的load()方法 来获取它。 load()的另一个参数是指定类的.class对象。
如果没有匹配的数据库记录,load()方法可能抛出无法恢复的异常(unrecoverable exception)。 如果类的映射使用了代理(proxy),load()方法会返回一个未初始化的代理,直到你调用该代理的某方法时才会去访问数据库。 若你希望在某对象中创建一个指向另一个对象的关联,又不想在从数据库中装载该对象时同时装载相关联的那个对象,那么这种操作方式就用得上的了。
任何时候都可以使用refresh()方法强迫装载对象和它的集合。
sess.save(cat);
sess.flush(); //force the SQL INSERT
sess.refresh(cat); //re-read the state (after the trigger executes)
重要问题: Hibernate会从数据库中装载多少东西?会执行多少条相应的SQLSELECT语句? 这取决于抓取策略(fetching strategy)。

查询对象:如果不知道所要寻找的对象的持久化标识,那么你需要使用查询。Hibernate支持强大且易于使用的面向对象查询语言(HQL)。 如果希望通过编程的方式创建查询,Hibernate提供了完善的按条件(Query By Criteria, QBC)以及按样例(Query By Example, QBE)进行查询的功能。 你也可以用原生SQL(native SQL)描述查询,Hibernate额外提供了将结果集(result set)转化为对象的支持。
HQL和原生SQL(native SQL)查询要通过为org.hibernate.Query的实例来表达。 这个接口提供了参数绑定、结果集处理以及运行实际查询的方法。 你总是可以通过当前Session获取一个Query对象。
一个查询通常在调用list()时被执行,执行结果会完全装载进内存中的一个集合(collection)。 查询返回的对象处于持久(persistent)状态。
注意,使用集合预先抓取的查询往往会返回多次根对象(他们的集合类都被初始化了)。你可以通过一个集合来过滤这些重复对象。
迭代式获取结果(Iterating results):你预期返回的结果在session,或二级缓存(second-level cache)中已经存在时的情况下,你可以使用iterate()方法得到更好的性能。iterate()会首先使用1条语句得到所有对象的持久化标识(identifiers),再根据持久化标识执行n条附加的select语句实例化实际的对象。
返回元组(tuples)的查询:元组(tuples)指一条结果行包含多个对象。
标量(Scalar)结果:查询可在select从句中指定类的属性,甚至可以调用SQL统计(aggregate)函数。 属性或统计结果被认定为"标量(Scalar)"的结果(而不是持久(persistent state)的实体)。
绑定参数:接口Query提供了对命名参数(named parameters)、JDBC风格的问号(?)参数进行绑定的方法。不同于JDBC,Hibernate对参数从0开始计数。 命名参数(named parameters)在查询字符串中是形如:name的标识符。
命名参数(named parameters)的优点是: 在查询串中出现的顺序无关、在同一查询串中可以多次出现、是本身的自我说明。
分页:如果你需要指定结果集的范围(希望返回的最大行数/或开始的行数),应该使用Query接口提供的方法。
外置命名查询:你可以在映射文件中定义命名查询(named queries)。
过滤集合:集合过滤器(filter)是一种用于一个持久化集合或者数组的特殊的查询。查询字符串中可以使用"this"来引用集合中的当前元素。
条件查询(Criteria queries):HQL极为强大,但是有些人希望能够动态的使用一种面向对象API创建查询,而非在他们的Java代码中嵌入字符串。对
使用原生SQL的查询:你可以使用createSQLQuery()方法,用SQL来描述查询,并由Hibernate将结果集转换成对象。 请注意,你可以在任何时候调用session.connection()来获得并使用JDBC Connection对象。

修改持久对象:事务中的持久实例(就是通过session装载、保存、创建或者查询出的对象) 被应用程序操作所造成的任何修改都会在Session被刷出(flushed)的时候被持久化,)。 这里不需要调用某个特定的方法(比如update(),设计它的目的是不同的)将你的修改持久化。
注意:Hibernate本身不提供直接执行UPDATE或DELETE语句的API。 Hibernate提供的是状态管理(state management)服务,你不必考虑要使用的语句(statements)。 JDBC是出色的执行SQL语句的API,任何时候调用session.connection()你都可以得到一个JDBC Connection对象。 此外,在联机事务处理(OLTP)程序中,大量操作(mass operations)与对象/关系映射的观点是相冲突的。 Hibernate的将来版本可能会提供专门的进行大量操作(mass operation)的功能。

修改脱管(Detached)对象:Hibernate通过提供Session.update()或Session.merge() 重新关联脱管实例的办法来支持这种模型。
如果你确定当前session没有包含与之具有相同持久化标识的持久实例,使用update()。 如果想随时合并你的的改动而不考虑session的状态,使用merge()。 换句话说,在一个新session中通常第一个调用的是update()方法,以便保证重新关联脱管(detached)对象的操作首先被执行。
如果希望相关联的脱管对象(通过引用“可到达”的脱管对象)的数据也要更新到数据库时(并且也仅仅在这种情况), 可以对该相关联的脱管对象单独调用update() 当然这些可以自动完成,即通过使用传播性持久化(transitive persistence)。
lock()方法也允许程序重新关联某个对象到一个新session上。不过,该脱管(detached)的对象必须是没有修改过的!

自动状态检测:Hibernate的用户曾要求一个既可自动分配新持久化标识(identifier)保存瞬时(transient)对象,又可更新/重新关联脱管(detached)实例的通用方法。
saveOrUpdate()用途和语义可能会使新用户感到迷惑。 首先,只要你没有尝试在某个session中使用来自另一session的实例,你就应该不需要使用update(), saveOrUpdate(),或merge()。

删除持久对象:使用Session.delete()会把对象的状态从数据库中移除。 当然,你的应用程序可能仍然持有一个指向已删除对象的引用。所以,最好这样理解:delete()的用途是把一个持久实例变成瞬时(transient)实例。

在两个不同数据库间复制对象:偶尔会用到不重新生成持久化标识(identifier),将持久实例以及其关联的实例持久到不同的数据库中的操作。

Session刷出(flush):每间隔一段时间,Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush)。
flush时间点概念。

传播性持久化(transitive persistence):
实体(entities)类型,而非值类型(value typed): 值类型(value typed)的对象不可能被其他对象引用;实体有自己的生命期,允许共享对其的引用(因此从集合中移除一个实体,不意味着它可以被删除), 并且实体到其他关联实体之间默认没有级联操作的设置。 Hibernate默认不实现所谓的可到达即持久化(persistence by reachability)的策略。
每个Hibernate session的基本操作 - 包括 persist(), merge(), saveOrUpdate(), delete(), lock(), refresh(), evict(), replicate() - 都有对应的级联风格(cascade style)。 这些级联风格(cascade style)风格分别命名为 create, merge, save-update, delete, lock, refresh, evict, replicate。 如果你希望一个操作被顺着关联关系级联传播,你必须在映射文件中指出这一点。

元数据:Hibernate中有一个非常丰富的元级别(meta-level)的模型,含有所有的实体和值类型数据的元数据。 Hibernate提供了ClassMetadata接口,CollectionMetadata接口和Type层次体系来访问元数据。 可以通过SessionFactory获取元数据接口的实例。

Hibernate的事务和并发控制很容易掌握。Hibernate直接使用JDBC连接和JTA资源,不添加任何附加锁定行为。我们强烈推荐你花点时间了解JDBC编程,ANSI SQL查询语言和你使用 的数据库系统的事务隔离规范。
Hibernate不锁定内存中的对象。你的应用程序会按照你的数据库事务的隔离级别规定的那样运作。幸亏有了Session,使得Hibernate通过标识符查找,和实体查询(不是返回标量值的报表查询)提供了可重复的读取(Repeatable reads)功能,Session同时也是事务范围内的缓存(cache)。
除了对自动乐观并发控制提供版本管理,针对行级悲观锁定,Hibernate也提供了辅助的(较小的)API,它使用了 SELECT FOR UPDATE的SQL语法。
从Configuration层、SessionFactory层, 和 Session层开始讨论Hibernate的并行控制、数据库事务和应用 程序的长事务。

Session和事务范围(transaction scope):
SessionFactory对象的创建代价很昂贵,它是线程安全的对象,它为所有的应用程序线程所共享。它只创建一次,通常是在应用程序启动的时候,由一个Configuraion的实例来创建。
Session对象的创建代价比较小,是非线程安全的,对于单个请求,单个会话、单个的 工作单元而言,它只被使用一次,然后就丢弃。只有在需要的时候,一个Session对象 才会获取一个JDBC的Connection(或一个Datasource) 对象,因此假若不使用的时候它不消费任何资源。
数据库事务应该尽可能的短,降低数据库中的锁争用。 数据库长事务会阻止你的应用程序扩展到高的并发负载。
问题来了哦:一个操作单元(Unit of work)的范围是多大?单个的Hibernate Session能跨越多个 数据库事务吗?还是一个Session的作用范围对应一个数据库事务的范围?应该何时打开 Session,何时关闭Session?,你又如何划分数据库事务的边界呢?

操作单元(Unit of work):
首先,别用session-per-operation这种反模式了,也就是说,在单个线程中, 不要因为一次简单的数据库调用,就打开和关闭一次Session!数据库事务也是如此。 应用程序中的数据库调用是按照计划好的次序,分组为原子的操作单元。(注意,这也意味着,应用程 序中,在单个的SQL语句发送之后,自动事务提交(auto-commit)模式失效了。这种模式专门为SQL控制台操作设计的。 Hibernate禁止立即自动事务提交模式,或者期望应用服务器禁止立即自动事务提交模式。)数据库事务绝不是可有可无的,任何与数据库之间的通讯都必须在某个事务中进行,不管你是在读还是在写数据。对读数据而言,应该避免auto-commit行为,因为很多小的事务比一个清晰定义的工作单元性能差。
注意,这也意味着,应用程序中,在单个的SQL语句发送之后,自动事务提交(auto-commit)模式失效了。这种模式专门为SQL控制台操作设计的。 Hibernate禁止立即自动事务提交模式,或者期望应用服务器禁止立即自动事务提交模式。
在多用户的client/server应用程序中,最常用的模式是 每个请求一个会话(session-per-request)。 在这种模式下,来自客户端的请求被发送到服务器端(即Hibernate持久化层运行的地方),一 个新的Hibernate Session被打开,并且执行这个操作单元中所有的数据库操作。 一旦操作完成(同时对客户端的响应也准备就绪),session被同步,然后关闭。你也可以使用单 个数据库事务来处理客户端请求,在你打开Session之后启动事务,在你关闭 Session之前提交事务。会话和请求之间的关系是一对一的关系,这种模式对 于大多数应用程序来说是很棒的。
Hibernate内置了对"当前session(current session)" 的管理,用于简化此模式。你要做的一切就是在服务器端要处理请求的时候,开启事务,在响应发送给客户之前结束事务。你可以用任何方式来完成这一操作,通常的方案有ServletFilter,在service方法中进行pointcut的AOP拦截器,或者proxy/interception容器。
在任何时间,任何地方,你的应用代码可以通过简单的调用sessionFactory.getCurrentSession()来访问"当前session",用于处理请求。你总是会得到当前数据库事务范围内的Session。在使用本地资源或JTA环境时,必须配置它。
将Session和数据库事务的边界延伸到"展示层被渲染后"会带来便利。有些serlvet应用程序在对请求进行处理后,有个单独的渲染期,这种延伸对这种程序特别有用。假若你实现你自己的拦截器,把事务边界延伸到展示层渲染结束后非常容易。然而,假若你依赖有容器管理事务的EJB,这就不太容易了,因为事务会在EJB方法返回后结束,而那是在任何展示层渲染开始之前。请访问Hibernate网站和论坛,你可以找到Open Session in View这一模式的提示和示例。

长对话:
session-per-request模式不仅仅是一个可以用来设计操作单元的有用概念。很多业务处理都需 要一系列完整的与用户之间的交互,而这些用户是指对数据库有交叉访问的用户。在基于web的应用和企业 应用中,跨用户交互的数据库事务是无法接受的。
解决方案:自动版本化、脱管对象(Detached Objects)、Extended (or Long) Session。session-per-request-with-detached-objects 和 session-per-conversation 各有优缺点。

关注对象标识(Considering object identity):
应用程序可能在两个不同的Session中并发访问同一持久化状态,但是, 一个持久化类的实例无法在两个 Session中共享。
当应用程序在两个不同的session中并发访问具有同一持久化标 识的业务对象实例的时候,这个业务对象的两个实例事实上是不相同的(从 JVM识别来看)。这种冲突可以通过在同步和提交的时候使用自动版本化和乐 观锁定方法来解决。
这种方式把关于并发的头疼问题留给了Hibernate和数据库。

决不要使用反模式session-per-user-session或者 session-per-application(当然,这个规定几乎没有例外)。
Session 对象是非线程安全的。
一个由Hibernate抛出的异常意味着你必须立即回滚数据库事务,并立即关闭Session 。如果你的Session绑定到一个应用程序上,你必须停止该应用程序。回滚数据库事务并不会把你的业务对象退回到事务启动时候的状态。这意味着数据库状态和业务对象状态不同步。
Session 缓存了处于持久化状态的每个对象(Hibernate会监视和检查脏数据)。 这意味着,如果你让Session打开很长一段时间,或是仅仅载入了过多的数据, Session占用的内存会一直增长,直到抛出OutOfMemoryException异常。这个问题的一个解决方法是调用clear() 和evict()来管理 Session的缓存,但是如果你需要大批量数据操作的话,最好考虑 使用存储过程。

数据库(或者系统)事务的声明总是必须的。在数据库事务之外,就无法和数据库通讯(这可能会让那些习惯于 自动提交事务模式的开发人员感到迷惑)。永远使用清晰的事务声明,即使只读操作也是如此。进行显式的事务声明并不总是需要的,这取决于你的事务隔离级别和数据库的能力,但不管怎么说,声明事务总归有益无害。
一个Hibernate应用程序可以运行在非托管环境中(也就是独立运行的应用程序,简单Web应用程序, 或者Swing图形桌面应用程序),也可以运行在托管的J2EE环境中。在一个非托管环境中,Hibernate 通常自己负责管理数据库连接池。应用程序开发人员必须手工设置事务声明,换句话说,就是手工启 动,提交,或者回滚数据库事务。
Hibernate提供了一套称为Transaction的封装API, 用来把你的部署环境中的本地事务管理系统转换到Hibernate事务上。这个API是可选的,但是我们强烈 推荐你使用,除非你用CMT session bean。
通常情况下,结束 Session 包含了四个不同的阶段: 同步session(flush,刷出到磁盘) 、提交事务 、关闭session 、处理异常 。

在托管和非托管环境下的事务声明和异常处理?????

非托管环境;
如果Hibernat持久层运行在一个非托管环境中,数据库连接通常由Hibernate的简单(即非DataSource)连接池机制 来处理。
Transaction tx =  factory.openSession().beginTransaction();以及  factory.getCurrentSession().beginTransaction();你应该选择 org.hibernate.transaction.JDBCTransactionFactory (这是默认选项),对第二个例子来说,hibernate.current_session_context_class应该是"thread" .

使用JTA:
如果你的持久层运行在一个应用服务器中,Hibernate获取 的每个数据源连接将自动成为全局JTA事务的一部分。
Hibernate提供了两种策略进行JTA集成:
如果你使用bean管理事务(BMT),可以通过使用Hibernate的 Transaction API来告诉 应用服务器启动和结束BMT事务。
在CMT方式下,事务声明是在session bean的部署描述符中,而不需要编程。
说明:在BMT或者CMT中,你根本就不需要使用Hibernate Transaction API ,你自动得到了绑定到事务的“当前”Session。

异常处理:
如果 Session 抛出异常 (包括任何SQLException), 你应该立即回滚数据库事务,调用 Session.close() ,丢弃该 Session实例。
Session的某些方法可能会导致session 处于不一致的状态。
所有由Hibernate抛出的异常都视为不可以恢复的。确保在 finally 代码块中调用close()方法,以关闭掉 Session。
HibernateException是一个非检查期异常, 它封装了Hibernate持久层可能出现的大多数错误。请注意,Hibernate也有可能抛出其他并不属于 HibernateException的非检查期异常。这些异常同样也是无法恢复的,应该 采取某些相应的操作去处理。
在和数据库进行交互时,Hibernate把捕获的SQLException封装为Hibernate的 JDBCException。

事务超时:
在托管(JTA)环境之外,Hibernate无法完全提供这一功能。但是,Hiberante至少可以控制数据访问,确保数据库级别的死锁,和返回巨大结果集的查询被限定在一个规定的时间内。在托管环境中,Hibernate会把事务超时转交给JTA。    sess.getTransaction().setTimeout(3);

乐观并发控制(Optimistic concurrency control):
唯一能够同时保持高并发和高可伸缩性的方法就是使用带版本化的乐观并发控制。版本检查使用版本号、 或者时间戳来检测更新冲突(并且防止更新丢失)。
Hibernate为使用乐观并发控制的代码提供了三种可能的方法:
1、应用程序级别的版本检查(Application version checking):迫使应用程序自己实现版本检查来确保 对话事务的隔离,从数据访问的角度来说是最低效的。
每次和数据库交互都需要一个新的 Session,而且开发人员必须在显示数据之前从数据库中重 新载入所有的持久化对象实例。
2、扩展周期的session和自动版本化:在一个旧session中开启一个新的数据库事务,会导致session获取一个新的连接,并恢复session的功能。
单个 Session实例和它所关联的所有持久化对象实例都被用于整个 对话,这被称为session-per-conversation(扩展session)。如果在用户思考的过程中,Session因为太大了而不能保存,那么这种模式是有 问题的。
3、脱管对象(deatched object)和自动版本化:与持久化存储的每次交互都发生在一个新的Session中。
应用程序操纵脱管对象实例 的状态,这个脱管对象实例最初是在另一个Session 中载入的,然后 调用 Session.update(),Session.saveOrUpdate(), 或者 Session.merge() 来重新关联该对象实例。
如果你确信对象没有被修改过,你也可以调用lock() 来设置 LockMode.READ(绕过所有的缓存,执行版本检查),从而取 代 update()操作。

悲观锁定(Pessimistic Locking):
通常情况下,只要为JDBC连接指定一下隔离级别,然后让数据库去搞定一切就够了。然而,高级用户有时候希望进行一个排它的悲观锁定, 或者在一个新的事务启动的时候,重新进行锁定。
Hibernate总是使用数据库的锁定机制,从不在内存中锁定对象!

连接释放模式(Connection Release Modes):
Session在第一次需要的时候获取一个连接,在session关闭之前一直会持有这个连接。Hibernate引入了连接释放的概念,来告诉session如何处理它的JDBC连接。

拦截器:
Interceptor接口提供了从会话(session)回调(callback)应用程序(application)的机制, 这种回调机制可以允许应用程序在持久化对象被保存、更新、删除或是加载之前,检查并(或)修改其 属性。
一个可能的用途,就是用来跟踪审核(auditing)信息。
拦截器可以有两种:Session范围内的,和SessionFactory范围内的。

事件系统:
Session接口的每个方法都有相对应的事件。
当某个方 法被调用时,Hibernate Session会生成一个相对应的事件并激活所有配置好的事件监听器。
系统预设的监听器实现的处理过程就是被监听的方法要做的(被监听的方法所做的其实仅仅是激活监听器, “实际”的工作是由监听器完成的)。
你可以自由地选择实现 一个自己定制的监听器(比如,实现并注册用来处理处理LoadEvent的LoadEventListener接口), 来负责处理所有的调用Session的load()方法的请求。
监听器应该被看作是单例(singleton)对象,也就是说,所有同类型的事件的处理共享同一个监听器实例,因此监听器不应该保存任何状态(也就是不应该使用成员变量)。
用户定制的监听器应该实现与所要处理的事件相对应的接口,或者从一个合适的基类继承,用户定制的监听器可以通过编程使用Configuration对象来注册,也可以在Hibernate的XML格式的配置文件中进行声明。

Hibernate3 提供了一种创新的方式来处理具有“显性(visibility)”规则的数据,那就是使用Hibernate filter。 Hibernate filter是全局有效的、具有名字、可以带参数的过滤器, 对于某个特定的Hibernate session您可以选择是否启用(或禁用)某个过滤器。
Hibernate 过滤器(filters):
过滤器条件相当于定义一个 非常类似于类和各种集合上的“where”属性的约束子句,但是过滤器条件可以带参数。
过滤器的用法很像数据库视图,只不过是在应用程序中确定使用什么样的参数的。

抓取策略(Fetching strategies):
当应用程序需要在(Hibernate实体对象图的)关联关系间进行导航的时候, Hibernate如何获取关联对象的策略。抓取策略可以在O/R映射的元数据中声明,也可以在特定的HQL 或条件查询(Criteria Query)中重载声明。
Hibernate3 定义了如下几种抓取策略:连接抓取(Join fetching)、查询抓取(Select fetching)、子查询抓取(Subselect fetching)、批量抓取(Batch fetching)。
Hibernate会区分下列各种情况:Immediate fetching、Lazy collection fetching、"Extra-lazy" collection fetching、Proxy fetching、"No-proxy" fetching、Lazy attribute fetching。
关联何时被抓取以及被如何抓取。

操作延迟加载的关联:
默认情况下,Hibernate 3对集合使用延迟select抓取,对返回单值的关联使用延迟代理抓取。然而,你必须了解延迟抓取带来的一个问题。在一个打开的Hibernate session上下文之外调用延迟集合会导致一次意外。
Hibernate对脱管对象不支持延迟实例化。
对绝大部分集合来说,更推荐使用延迟方式抓取数据。如果在你的对象模型中定义了太多的非延迟关联,Hibernate最终几乎需要在每个事务中载入整个数据库到内存中!
在一些特殊的事务中,我们也经常需要使用到连接抓取(它本身上就是非延迟的),以代替查询抓取。

通常情况下,我们并不使用映射文档进行抓取策略的定制。更多的是,保持其默认值,然后在特定的事务中, 使用HQL的左连接抓取(left join fetch) 对其进行重载。这将通知 Hibernate在第一次查询中使用外部关联(outer join),直接得到其关联数据。 在条件查询 API中,应该调用 setFetchMode(FetchMode.JOIN)语句。

单端关联代理(Single-ended association proxies):
单端关联的目标实体必须使用代理,Hihernate在运行期二进制级(通过优异的CGLIB库), 为持久对象实现了延迟载入代理。

实例化集合和代理(Initializing collections and proxies):
在Session范围之外访问未初始化的集合或代理,Hibernate将会抛出LazyInitializationException异常。 也就是说,在分离状态下,访问一个实体所拥有的集合,或者访问其指向代理的属性时,会引发此异常。
在一个基于Web的应用中,可以利用servlet过滤器(filter),在用户请求(request)结束、页面生成 结束时关闭Session(这里使用了在展示层保持打开Session模式(Open Session in View)), 当然,这将依赖于应用框架中异常需要被正确的处理。在返回界面给用户之前,乃至在生成界面过程中发生异常的情况下, 正确关闭Session和结束事务将是非常重要的。

使用批量抓取(Using batch fetching):
Hibernate可以充分有效的使用批量抓取,也就是说,如果仅一个访问代理(或集合),那么Hibernate将不载入其他未实例化的代理。 批量抓取是延迟查询抓取的优化方案,你可以在两种批量抓取方案之间进行选择:在类级别和集合级别。

使用子查询抓取(Using subselect fetching):
假若一个延迟集合或单值代理需要抓取,Hibernate会使用一个subselect重新运行原来的查询,一次性读入所有的实例。

使用延迟属性抓取(Using lazy property fetching):
Hibernate3对单独的属性支持延迟抓取,这项优化技术也被称为组抓取(fetch groups)。

二级缓存(The Second Level Cache):
Hibernate的Session在事务级别进行持久化数据的缓存操作。 当然,也有可能分别为每个类(或集合),配置集群、或JVM级别(SessionFactory级别)的缓存。 你甚至可以为之插入一个集群的缓存。
注意,缓存永远不知道其他应用程序对持久化仓库(数据库)可能进行的修改 (即使可以将缓存数据设定为定期失效)。
通过在hibernate.cache.provider_class属性中指定org.hibernate.cache.CacheProvider的某个实现的类名,你可以选择让Hibernate使用哪个缓存实现。

缓存映射(Cache mappings):usage(必须)说明了缓存的策略\region (可选, 默认为类或者集合的名字(class or collection role name)) \include (可选,默认为 all) 。
策略:只读缓存(Strategy: read only);
策略:读/写缓存(Strategy: read/write):
策略:非严格读/写缓存(Strategy: nonstrict read/write):
策略:事务缓存(transactional):

管理缓存(Managing the caches):
无论何时,当你给save()、update()或 saveOrUpdate()方法传递一个对象时,或使用load()、 get()、list()、iterate() 或scroll()方法获得一个对象时, 该对象都将被加入到Session的内部缓存中。
当随后flush()方法被调用时,对象的状态会和数据库取得同步。
如果你不希望此同步操作发生,或者你正处理大量对象、需要对有效管理内存时,你可以调用evict() 方法,从一级缓存中去掉这些对象及其集合。
Session还提供了一个contains()方法,用来判断某个实例是否处于当前session的缓存中。
如若要把所有的对象从session缓存中彻底清除,则需要调用Session.clear()。
对于二级缓存来说,在SessionFactory中定义了许多方法, 清除缓存中实例、整个类、集合实例或者整个集合。
如若需要查看二级缓存或查询缓存区域的内容,你可以使用统计(Statistics) API。

查询缓存(The Query Cache:
查询的结果集也可以被缓存。
首先你必须打开它:hibernate.cache.use_query_cache=true
该设置将会创建两个缓存区域 - 一个用于保存查询结果集(org.hibernate.cache.StandardQueryCache); 另一个则用于保存最近查询的一系列表的时间戳(org.hibernate.cache.UpdateTimestampsCache)。
查询缓存通常会和二级缓存一起使用。

监测性能(Monitoring performance):
没有监测和性能参数而进行优化是毫无意义的。Hibernate为其内部操作提供了一系列的示意图,因此可以从 每个SessionFactory抓取其统计数据。
监测SessionFactory:
你可以有两种方式访问SessionFactory的数据记录,第一种就是自己直接调用 sessionFactory.getStatistics()方法读取、显示统计数据。 如果你打开StatisticsService MBean选项,那么Hibernate则可以使用JMX技术 发布其数据记录。你可以让应用中所有的SessionFactory同时共享一个MBean,也可以每个 SessionFactory分配一个MBean。
数据记录(Metrics):
Hibernate提供了一系列数据记录,其记录的内容包括从最基本的信息到与具体场景的特殊信息。所有的测量值都可以由 Statistics接口进行访问,主要分为三类:
1、使用Session的普通数据记录,例如打开的Session的个数、取得的JDBC的连接数等;
2、实体、集合、查询、缓存等内容的统一数据记录
3、和具体实体、集合、查询、缓存相关的详细数据记录。

分享到:
评论

相关推荐

    尚学堂hibernate学习笔记(原版整理)

    【尚学堂Hibernate学习笔记】是一份详尽的学习资料,旨在...总之,这份尚学堂Hibernate学习笔记是全面了解和学习Hibernate的宝贵资料,不仅涵盖了基础概念,还深入到实践操作和高级话题,适合初学者和进阶者共同参考。

    hibernate学习资料大合集

    这两份笔记可能由经验丰富的开发者整理,包含他们在学习和使用Hibernate过程中积累的实用技巧和常见问题解决方案。这些个人经验往往能提供独特的视角和实战经验,对于解决实际问题非常有价值。 通过这些资料的学习...

    hibernate框架学习笔记整理

    ### hibernate框架学习笔记整理 #### 一、Hibernate框架简介 **Hibernate框架**是一种用于Java应用的**对象关系映射**(Object-Relational Mapping, ORM)解决方案,它允许开发者使用面向对象的方式操作数据库中的表...

    hibernate学习必用

    本资源包“hibernate学习必用”正是针对Hibernate的学习者精心整理的,包含了关键的组件和依赖,旨在帮助初学者快速入门并深入理解Hibernate的核心功能。 首先,我们来看看“hibernate annotations”。这部分内容...

    Hibernate知识整理.doc

    【Hibernate 知识整理】 1- Hibernate 是什么? Hibernate 是一个流行的对象关系映射(ORM)框架,它允许 Java 开发者用面向对象的方式来处理数据库...同时,掌握 ORM 和日志管理的基本概念,能进一步提升开发能力。

    邹波老师Hibernate教程学习笔记

    这是一份由个人在观看邹波老师的Hibernate视频教程后精心整理的学习笔记,旨在帮助初学者和有一定基础的程序员更好地理解和运用Hibernate。Hibernate作为Java领域广泛使用的持久化框架,它极大地简化了数据库操作,...

    黑马49期Hibernate学习

    【描述】中提到的“完整的笔记”可能包括了Hibernate的基本概念、核心API、配置、实体关系映射(ORM)、数据访问对象(DAO)设计模式、事务管理、缓存机制、查询语言(HQL)和 Criteria API等内容。这些笔记将帮助...

    达内HIBERNATE学习笔记

    - 理解Hibernate的基本概念。 - 掌握如何使用Hibernate进行开发。 #### 1.2 对象持久化 - **定义**:对象持久化是指将程序中的对象状态保存到永久存储介质(如硬盘)上的过程。 - **作用**:使得对象的状态能够在...

    关于Struts1&2 Spring Hibernate 三大框架学习综合整理

    这篇文档将深入探讨这三大框架的基本概念、工作原理以及它们之间的协同工作方式。 **Struts1框架** Struts1是Apache软件基金会的一个开源项目,主要解决MVC(Model-View-Controller)设计模式在Java Web应用中的...

    hibernate3入门

    - **2005年3月**:Hibernate 3 正式发布,相比前一版本有重大改变,这份文档将以之前Hibernate 2 的文档为基础,针对Hibernate 3 进行重新整理的工作,使用的版本为Hibernate 3.0。 #### 三、基础入门 **基础入门*...

    hibernate 3.2中文手册 中文文档

    - 介绍了Hibernate的基本概念及其重要性。 - 强调了学习Hibernate对于Java开发人员的重要性。 - **1.2 第一部分—第一个Hibernate应用程序** - **1.2.1 第一个Class** - 创建一个简单的Java类作为持久化对象的...

    hibernate官方入门教程 (转载)

    标题“hibernate官方入门教程 (转载)”表明这是一份关于Hibernate框架的基础教学资源,可能是从官方文档或者其他可靠来源整理而来的,适合初学者了解和学习Hibernate。 描述中提到的“NULL”意味着没有具体的描述...

    Hibernate学习笔记

    这些知识点包括了Hibernate的基本概念、配置文件、核心API以及具体的数据库操作等内容。 ### Hibernate 概念 #### 什么是Hibernate? Hibernate是一种开源的对象关系映射(Object-Relational Mapping,简称ORM)...

    Hibernate_PDF_超好

    再者,"Hibernate笔记.pdf"可能是一位资深开发者或讲师整理的个人学习笔记,通常会包含一些实践经验和技巧。这类笔记往往能提供一些官方文档中未提及的实用小贴士,如常见错误的解决方案、最佳实践以及一些性能调优...

    Hibernate入门.rar

    【Hibernate入门】是一个针对初学者精心整理的教程资源包,旨在帮助新手快速理解并掌握Java持久化框架Hibernate的核心概念和使用方法。这个压缩包包含了所有你需要开始Hibernate学习的基础材料。 Hibernate是一个...

    Hibernate文档资料

    其次,`Hibernate学习笔记`可能是个人或社区在学习过程中整理的实用技巧和常见问题解答,这些笔记往往包含实践案例,能帮助读者快速解决实际开发中遇到的问题。例如,它们可能会讲解如何处理关联映射,如一对一、一...

    hibernate+struts 入门PPT

    在本教程中,首先会介绍Struts框架的基本概念。Struts将应用程序分为模型、视图和控制器三个部分,通过Action类处理用户请求,并将处理结果传递给相应的JSP页面进行展示。开发者会学习如何创建ActionForm、配置...

    夏昕-Hibernate+开发指南.pdf

    - **Hibernate基础语义**:包括Configuration、SessionFactory、Session等概念及其使用方法。 - **Hibernate高级特性**:涵盖了XDoclet与Hibernate映射、数据检索、HQL语言、数据关联等进阶主题。 - **数据访问**...

    java学习笔记(文字整理版).doc

    通过对核心概念和技术点的详细解释,使学习者能够快速上手Java及Hibernate。 #### 二、Java基础知识概览 - **HelloWorld**:Java程序入门的第一个示例,用于展示如何在控制台输出“Hello World!”,是学习任何编程...

    java学习指导及面向对象基础知识整理

    对于想要提高网络编程能力的学习者来说,可以学习JSP、Servlet等技术,以及SSH(Spring、Struts2、Hibernate)框架。Spring框架尤其受到业界青睐,掌握Spring对于想要进入企业级应用开发的程序员尤为重要。 Java...

Global site tag (gtag.js) - Google Analytics