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

Hibernate整理学习之基础概念1

阅读更多

基于控制台的(console-based)Hibernate应用程序,我们使用Java数据库(HSQL DB),不必安装任何数据库服务器。
所有的持久化类(persistent classes)都要求有无参的构造器,因为Hibernate必须使用Java反射机制来为你创建对象。
Hibernate需要知道怎样去加载(load)和存储(store)持久化类的对象。
SessionFactory-一个关联于特定数据库全局的工厂(factory)。如果你要使用多个数据库,就要用多个的<session-factory>,通常把它们放在多个配置文件中(为了更容易启动)。
SessionFactory可以创建并打开新的Session。一个Session代表一个单线程的单元操作,SessionFactory则是个线程安全的全局对象,只需要被实例化一次。
静态初始化过程(仅当加载这个类的时候被JVM执行一次)中产生全局的SessionFactory,而且隐藏了它使用了静态singleton的事实。
单态类以及单态的区别??
Session在第一次被使用的时候,即第一次调用getCurrentSession()的时候,其生命周期就开始。然后它被Hibernate绑定到当前线程。当事务结束的时候,不管是提交还是回滚,Hibernate会自动把Session从当前线程剥离,并且关闭它。假若你再次调用getCurrentSession(),你会得到一个新的Session,并且开始一个新的工作单元。这种线程绑定(thread-bound)的编程模型(model)是使用Hibernate的最广泛的方式。Hibernate Session的生命周期可以很灵活,但是你绝不要把你的应用程序设计成为每一次数据库操作都用一个新的Hibernate Session。
关联方向(directionality),阶数(multiplicity)和集合(collection)的行为??
工作单元由数据库事务的提交(或者回滚)来结束——这是由CurrentSessionContext类的thread配置选项定义的。
不要为每次数据库操作都使用一个新的Hibernate Session。将Hibernate Session的范围设置为整个请求。要用getCurrentSession(),这样它自动会绑定到当前Java线程。
Open Session in View—只要你考虑用JSP来渲染你的视图(view),而不是在servlet中,你就会很快用到它。
每次请求一个session(session-per-request)。当有请求到达这个servlet的时候,通过对SessionFactory的第一次调用,打开一个新的Hibernate Session。然后启动一个数据库事务—所有的数据访问都是在事务中进行,不管是读还是写。
Hibernate使用数据库和配置信息来为应用程序提供持久化服务(以及持久的对象)。
主要的Hibernate概念:
1、SessionFactory (org.hibernate.SessionFactory): 针对单个数据库映射关系经过编译后的内存镜像,是线程安全的(不可变)。 它是生成Session的工厂,本身要用到ConnectionProvider。 该对象可以在进程或集群的级别上,为那些事务之间可以重用的数据提供可选的二级缓存。
2、Session (org.hibernate.Session):表示应用程序与持久储存层之间交互操作的一个单线程对象,此对象生存期很短。 其隐藏了JDBC连接,也是Transaction的工厂。 其会持有一个针对持久化对象的必选(第一级)缓存,在遍历对象图或者根据持久化标识查找对象时会用到。
3、持久的对象及其集合:带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。 这些对象可能是普通的JavaBeans/POJO,唯一特殊的是他们正与(仅仅一个)Session相关联。 一旦这个Session被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用。
4、瞬态(transient)和脱管(detached)的对象及其集合:那些目前没有与session关联的持久化类实例。 他们可能是在被应用程序实例化后,尚未进行持久化的对象。 也可能是因为实例化他们的Session已经被关闭而脱离持久化的对象。
5、事务Transaction (org.hibernate.Transaction):应用程序用来指定原子操作单元范围的对象,它是单线程的,生命周期很短。 它通过抽象将应用从底层具体的JDBC、JTA以及CORBA事务隔离开。 某些情况下,一个Session之内可能包含多个Transaction对象。 尽管是否使用该对象是可选的,但无论是使用底层的API还是使用Transaction对象,事务边界的开启与关闭是必不可少的。
6、ConnectionProvider (org.hibernate.connection.ConnectionProvider):生成JDBC连接的工厂(同时也起到连接池的作用)。 它通过抽象将应用从底层的Datasource或DriverManager隔离开。
7、TransactionFactory (org.hibernate.TransactionFactory):生成Transaction对象实例的工厂。
在特定“轻型”的体系结构中,应用程序可能绕过 Transaction/TransactionFactory 以及 ConnectionProvider 等API直接跟JTA或JDBC打交道。
实例状态:瞬态(transient) 、持久化(persistent) 、脱管(detached) ,一个持久化类的实例可能处于三种不同状态中的某一种。
JMX是管理Java组件(Java components)的J2EE标准。 Hibernate 可以通过一个JMX标准服务来管理。 在这个发行版本中,我们提供了一个MBean接口的实现,即 org.hibernate.jmx.HibernateService。 将Hibernate以部署为JMX服务的另一个好处,是可以查看Hibernate的运行时统计信息。
上下文相关的(Contextual)Session:JTASessionContext、ThreadLocalSessionContext、ManagedSessionContext。
org.hibernate.context.CurrentSessionContext接口:Hibernate内置了此接口的三种实现。1、org.hibernate.context.JTASessionContext - 当前session根据JTA来跟踪和界定;2、org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线程来跟踪和界定;3、org.hibernate.context.ManagedSessionContext - 当前session通过当前执行的线程来跟踪和界定。但是,你需要负责使用这个类的静态方法将Session实例绑定、或者取消绑定,它并不会打开(open)、flush或者关闭(close)任何Session。
Hibernate session的起始和终结由数据库事务的生存来控制。假若你在纯粹的 Java SE之上采用自行编写代码来管理事务,而不使用JTA,建议你使用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你使用JTA,请使用JTA借口来管理Transaction。如果你在支持CMT的EJB容器中执行代码,事务边界是声明式定义的,你不需要在代码中进行任何事务或session管理操作。
hibernate.current_session_context_class配置参数定义了应该采用哪个org.hibernate.context.CurrentSessionContext实现。

由于Hibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数。
一个org.hibernate.cfg.Configuration实例代表了一个应用程序中Java类型到SQL数据库映射的完整集合. Configuration被用来构建一个(不可变的 (immutable))SessionFactory.
Configuration实例被设计成启动期间(startup-time)对象, 一旦SessionFactory创建完成它就被丢弃了.
当所有映射定义被Configuration解析后, 应用程序必须获得一个用于构造Session实例的工厂. 这个工厂将被应用程序的所有线程共享: SessionFactory sessions = cfg.buildSessionFactory();
Hibernate允许你的应用程序创建多个SessionFactory实例.
使用SessionFactory来为你创建和缓存(pool)JDBC连接,我们需要向Hibernate传递一些JDBC连接的属性,所有Hibernate属性的名字和语义都在org.hibernate.cfg.Environment中定义。
Hibernate将使用java.sql.DriverManager来获得(和缓存)JDBC连接 。C3P0是一个随Hibernate一同分发的开源的JDBC连接池。
为了能在应用程序服务器中使用Hibernate, 应当总是将Hibernate 配置成从注册在JNDI中的Datasource处获得连接。从JNDI数据源获得的JDBC连接将自动参与到应用程序服务器中容器管理的事务(container-managed transactions)中去。
控制Hibernate在运行期的行为的可选配置属性 :Hibernate JDBC和连接(connection)属性 、Hibernate缓存属性 、Hibernate事务属性 、其他属性 。
注意SQL方言的配置。
二级缓存与查询缓存:以hibernate.cache为前缀的属性允许你在Hibernate中,使用进程或群集范围内的二级缓存系统.
Hibernate的统计(statistics)机制:如果你开启hibernate.generate_statistics, 那么当你通过 SessionFactory.getStatistics()调整正在运行的系统时,Hibernate将导出大量有用的数据. Hibernate甚至能被配置成通过JMX导出这些统计信息.
Hibernate使用Apache commons-logging来为各种事件记录日志,commons-logging将直接输出到Apache Log4j(如果在类路径中包括log4j.jar)或 JDK1.4 logging (如果运行在JDK1.4或以上的环境下)。
在hibernate.cfg.xml文件中可以指定一套完整的配置,这个文件可以当成hibernate.properties的替代。
J2EE应用程序服务器的集成:
1、容器管理的数据源(Container-managed datasources): Hibernate能使用通过容器管理,并由JNDI提供的JDBC连接.
2、自动JNDI绑定: Hibernate可以在启动后将 SessionFactory绑定到JNDI.
3、JTA Session绑定: Hibernate Session 可以自动绑定到JTA事务作用的范围.
4、JMX部署: 如果你使用支持JMX应用程序服务器(如, JBoss AS), 那么你可以选择将Hibernate部署成托管MBean.
事务策略配置:在你的架构中,Hibernate的Session API是独立于任何事务分界系统的;为了让你的代码在两种(或其他)环境中可以移植,我们建议使用可选的Hibernate Transaction API, 它包装并隐藏了底层系统.
指定 一个Transaction实例的工厂类,有三个标准(内建)的选择: org.hibernate.transaction.JDBCTransactionFactory 、org.hibernate.transaction.JTATransactionFactory 、org.hibernate.transaction.CMTTransactionFactory 。
JNDI绑定的SessionFactory:与JNDI绑定的Hibernate的SessionFactory能简化工厂的查询,简化创建新的Session.
在JTA环境下使用Current Session context管理:在Hibernate中,管理Session和transaction最好的方法是自动的"当前"Session管理。在"jta"上下文中调用getCurrentSession()获得的Session,会被设置为在transaction关闭的时候自动flush(清洗)、在transaction关闭之后自动关闭,每句语句之后主动释放JDBC连接。
JMX部署:为了部署在一个支持JMX的应用程序服务器上,Hibernate和 org.hibernate.jmx.HibernateService一同分发,如Jboss AS。

持久化类:在应用程序中,用来实现业务问题实体的类就是持久化类。不能认为所有的持久化类的实例都是持久的状态——一个实例的状态也可能是瞬时的或脱管的。简单传统Java对象(POJO:Plain Old Java Object)。
一个持久化类遵循四条主要的规则:实现一个默认的(即无参数的)构造方法(constructor)、提供一个标识属性(identifier property)(可选) 、使用非final的类 (可选)、为持久化字段声明访问器(accessors)和是否可变的标志(mutators)(可选)。
代理(proxies)是Hibernate的一个重要的功能,它依赖的条件是,持久 化类或者是非final的,或者是实现了一个所有方法都声明为public的接口。 你可以用Hibernate持久化一个没有实现任何接口的final类,但是你 不能使用代理来延迟关联加载,这会限制你进行性能优化的选择。 你也应该避免在非final类中声明 public final的方法。如果你想使用一 个有public final方法的类,你必须通过设置lazy="false" 来明确地禁用代理。
如果你有如下需求,你必须重载 equals() 和 hashCode()方法: 1、想把持久类的实例放入Set中(当表示多值关联时,推荐这么做) 2、想重用脱管实例 3、Hibernate保证,仅在特定会话范围内,持久化标识(数据库的行)和Java标识是等价的。因此,一旦 我们混合了从不同会话中获取的实例,如果希望Set有明确的语义,就必 须实现equals() 和hashCode()。
实现equals()/hashCode()最显而易见的方法是比较两个对象 标识符的值。这不是Hibernate的问题,而是一般的Java对象标识和Java对象等价的语义问题。建议使用业务键值相等(Business key equality)来实现equals() 和 hashCode()。业务键值相等的意思是,equals()方法 仅仅比较形成业务键的属性,它能在现实世界里标识我们的实例(是一个自然的候选码)。

动态模型(Dynamic models):运行期的持久化实体没有必要一定表示为像POJO类或JavaBean对象那样的形式。Hibernate也支持动态模型 (在运行期使用Map的Map)和象DOM4J的树模型那 样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics