第4章 配置
由于Hibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数. 幸运的是多数配置参数都 有比较直观的默认值, 并有随Hibernate一同分发的配置样例hibernate.properties (位于etc/ )来展示各种配置选项. 所需做的仅仅是将这个样例文件复制到类路径 (classpath)下做一些自定义的修改.
4.1. 可编程的配置方式
一个org.hibernate.cfg.Configuration 实例代表了一个应用程序中Java类型 到SQL数据库映射的完整集合. Configuration 被用来构建一个(不可变的 (immutable))SessionFactory . 映射定义则由不同的XML映射定义文件编译而来.
你可以直接实例化Configuration 来获取一个实例,并为它指定XML映射定义 文件. 如果映射定 义文件在类路径(classpath)中, 请使用addResource() :
Configuration cfg = new Configuration()
.addResource("Item.hbm.xml")
.addResource("Bid.hbm.xml");一个替代方法(有时是更好的选择)是,指定被映射的类,让Hibernate帮你寻找映射定义文件:
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class);Hibernate将会在类路径(classpath)中寻找名字为 /org/hibernate/auction/Item.hbm.xml 和 /org/hibernate/auction/Bid.hbm.xml 映射定义文件. 这种方式消除了任何对文件名的硬编码(hardcoded).
Configuration 也允许你指定配置属性:
Configuration cfg = new Configuration()
.addClass(org.hibernate.auction.Item.class)
.addClass(org.hibernate.auction.Bid.class)
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true");当然这不是唯一的传递Hibernate配置属性的方式, 其他可选方式还包括:
传一个java.util.Properties 实例给 Configuration.setProperties() .
将hibernate.properties 放置在类路径(classpath)的根目录下 (root directory).
通过java -Dproperty=value 来设置系统 (System )属性.
在hibernate.cfg.xml 中加入元素 (稍后讨论).
如果想尽快体验Hbernate, hibernate.properties 是最简单的方式.
Configuration 实例是一个启动期间(startup-time)的对象, 一旦SessionFactory 创建完成它就被丢弃了.
4.2. 获得SessionFactory
当所有映射定义被Configuration 解析后, 应用程序必须获得一个用于构造Session 实例的工厂. 这个工厂将被应用程序的所有线程共享:
SessionFactory sessions = cfg.buildSessionFactory();Hibernate允许你的应用程序创建多个SessionFactory 实例. 这对 使用多个数据库的应用来说很有用.
4.3. JDBC连接
通常你希望SessionFactory 来为你创建和缓存(pool)JDBC连接. 如果你采用这种方式, 只需要如下例所示那样,打开一个Session :
Session session = sessions.openSession(); // open a new Session一旦你需要进行数据访问时, 就会从连接池(connection pool)获得一个JDBC连接.
为了使这种方式工作起来, 我们需要向Hibernate传递一些JDBC连接的属性. 所有Hibernate属性的名字和语义都在org.hibernate.cfg.Environment 中定义. 我们现在将描述JDBC连接配置中最重要的设置.
如果你设置如下属性,Hibernate将使用java.sql.DriverManager 来获得(和缓存)JDBC连接 :
表4.1. Hibernate JDBC属性
属性名 用途 hibernate.connection.driver_class jdbc驱动类 hibernate.connection.url jdbc URL hibernate.connection.username 数据库用户 hibernate.connection.password 数据库用户密码 hibernate.connection.pool_size 连接池容量上限数目
但Hibernate自带的连接池算法相当不成熟. 它只是为了让你快些上手,不适合用于产品系统 或性能测试中。 出于最佳性能和稳定性考虑你应该使用第三方的连接池。只需要连接池的特定设置替换 hibernate.connection.pool_size 。这将关闭Hibernate自带的连接池. 例如, 你可能会想用C3P0.
C3P0是一个随Hibernate一同分发的开源的JDBC连接池, 它位于lib 目录下。 如果你设置了hibernate.c3p0.* 相关的属性, Hibernate将使用 C3P0ConnectionProvider 来缓存JDBC连接. 如果你更原意使用Proxool, 请参考发 行包中的hibernate.properties 并到Hibernate网站获取更多的信息.
这是一个使用C3P0的hibernate.properties 样例文件:
hibernate.connection.driver_class = org.postgresql.Driver
hibernate.connection.url = jdbc:postgresql://localhost/mydatabase
hibernate.connection.username = myuser
hibernate.connection.password = secret
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect为了能在应用程序服务器(application server)中使用Hibernate, 你应当总是将Hibernate 配置成注册在JNDI中的Datasource 处获得连接,你至少需要设置下列属性中的一个:
表4.2. Hibernate数据源属性
属性名 用途 hibernate.connection.datasource 数据源JNDI名字 hibernate.jndi.url JNDI提供者的URL (可选) hibernate.jndi.class JNDI InitialContextFactory 类 (可选) hibernate.connection.username 数据库用户 (可选) hibernate.connection.password 数据库用户密码 (可选)
这里有一个使用应用程序服务器JNDI数据源的hibernate.properties 样例文件:
hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = /
org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = /
org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect从JNDI数据源获得的JDBC连接将自动参与应用程序服务器中容器管理的事务(container-managed transactions)中去.
任何连接(connection)配置属性的属性名要以"hibernate.connnection "前缀开头. 例如, 你可能会使用hibernate.connection.charSet 来指定charSet .
通过实现org.hibernate.connection.ConnectionProvider 接口,你可以定义属于 你自己的获得JDBC连接的插件策略。通过设置hibernate.connection.provider_class , 你可以选择一个自定义的实现.
4.4. 可选的配置属性
有大量属性能用来控制Hibernate在运行期的行为. 它们都是可选的, 并拥有适当的默认值.
警告: 其中一些属性是"系统级(system-level)的". 系统级属性可以通过java -Dproperty=value 或 hibernate.properties 来设置, 而不能 用上面描述的其他方法来设置.
表4.3. Hibernate配置属性
属性名 用途 hibernate.dialect 一个Hibernate Dialect 类名允许Hibernate针对特定的关系数据库生成优化的SQL.
取值 full.classname.of.Dialect
hibernate.show_sql 输出所有SQL语句到控制台.
取值 true | false
hibernate.default_schema 在生成的SQL中, 将给定的schema/tablespace附加于非全限定名的表名上.
取值 SCHEMA_NAME
hibernate.default_catalog 在生成的SQL中, 将给定的catalog附加于没全限定名的表名上.
取值 CATALOG_NAME
hibernate.session_factory_name SessionFactory 创建后,将自动使用这个名字绑定到JNDI中.
取值 jndi/composite/name
hibernate.max_fetch_depth 为单向关联(一对一, 多对一)的外连接抓取(outer join fetch)树设置最大深度. 值为0 意味着将关闭默认的外连接抓取.
取值 建议在0 到3 之间取值
hibernate.default_batch_fetch_size 为Hibernate关联的批量抓取设置默认数量.
取值 建议的取值为4 , 8 , 和16
hibernate.default_entity_mode 为由这个SessionFactory 打开的所有Session指定默认的实体表现模式.
取值 dynamic-map , dom4j , pojo
hibernate.order_updates 强制Hibernate按照被更新数据的主键,为SQL更新排序。这么做将减少在高并发系统中事务的死锁。
取值 true | false
hibernate.generate_statistics 如果开启, Hibernate将收集有助于性能调节的统计数据.
取值 true | false
hibernate.use_identifer_rollback 如果开启, 在对象被删除时生成的标识属性将被重设为默认值.
取值 true | false
hibernate.use_sql_comments 如果开启, Hibernate将在SQL中生成有助于调试的注释信息, 默认值为false .
取值 true | false
表4.4. Hibernate JDBC和连接(connection)属性
属性名 用途 hibernate.jdbc.fetch_size 非零值,指定JDBC抓取数量的大小 (调用Statement.setFetchSize() ). hibernate.jdbc.batch_size 非零值,允许Hibernate使用JDBC2的批量更新.
取值 建议取5 到30 之间的值
hibernate.jdbc.batch_versioned_data 如果你想让你的JDBC驱动从executeBatch() 返回正确的行计数 , 那么将此属性设为true (开启这个选项通常是安全的). 同时,Hibernate将为自动版本化的数据使用批量DML. 默认值为false .
eg. true | false
hibernate.jdbc.factory_class 选择一个自定义的Batcher . 多数应用程序不需要这个配置属性.
eg. classname.of.Batcher
hibernate.jdbc.use_scrollable_resultset 允许Hibernate使用JDBC2的可滚动结果集. 只有在使用用户提供的JDBC连接时,这个选项才是必要的, 否则Hibernate会使用连接的元数据.
取值 true | false
hibernate.jdbc.use_streams_for_binary 在JDBC读写binary (二进制) 或serializable (可序列化) 的类型时使用流(stream)(系统级属性).
取值 true | false
hibernate.jdbc.use_get_generated_keys 在数据插入数据库之后,允许使用JDBC3 PreparedStatement.getGeneratedKeys() 来获取数据库生成的key(键)。需要JDBC3+驱动和JRE1.4+, 如果你的数据库驱动在使用Hibernate的标 识生成器时遇到问题,请将此值设为false. 默认情况下将使用连接的元数据来判定驱动的能力.
取值 true|false
hibernate.connection.provider_class 自定义ConnectionProvider 的类名, 此类用来向Hibernate提供JDBC连接.
取值 classname.of.ConnectionProvider
hibernate.connection.isolation 设置JDBC事务隔离级别. 查看java.sql.Connection 来了解各个值的具体意义, 但请注意多数数据库都不支持所有的隔离级别.
取值 1, 2, 4, 8
hibernate.connection.autocommit 允许被缓存的JDBC连接开启自动提交(autocommit) (不建议).
取值 true | false
hibernate.connection.release_mode 指定Hibernate在何时释放JDBC连接. 默认情况下,直到Session被显式关闭或被断开连接时,才会释放JDBC连接. 对于应用程序服务器的JTA数据源, 你应当使用after_statement , 这样在每次JDBC调用后,都会主动的释放连接. 对于非JTA的连接, 使用after_transaction 在每个事务结束时释放连接是合理的. auto 将为JTA和CMT事务策略选择after_statement , 为JDBC事务策略选择after_transaction .
取值 on_close | after_transaction | after_statement | auto
hibernate.connection. 将JDBC属性propertyName 传递到DriverManager.getConnection() 中去. hibernate.jndi. 将属性propertyName 传递到JNDI InitialContextFactory 中去.
表4.5. Hibernate缓存属性
属性名 用途 hibernate.cache.provider_class 自定义的CacheProvider 的类名.
取值 classname.of.CacheProvider
hibernate.cache.use_minimal_puts 以频繁的读操作为代价, 优化二级缓存来最小化写操作. 在Hibernate3中,这个设置对的集群缓存非常有用, 对集群缓存的实现而言,默认是开启的.
取值 true|false
hibernate.cache.use_query_cache 允许查询缓存, 个别查询仍然需要被设置为可缓存的.
取值 true|false
hibernate.cache.use_second_level_cache 能用来完全禁止使用二级缓存. 对那些在类的映射定义中指定 的类,会默认开启二级缓存.
取值 true|false
hibernate.cache.query_cache_factory 自定义的实现QueryCache 接口的类名, 默认为内建的StandardQueryCache .
取值 classname.of.QueryCache
hibernate.cache.region_prefix 二级缓存区域名的前缀.
取值 prefix
hibernate.cache.use_structured_entries 强制Hibernate以更人性化的格式将数据存入二级缓存.
取值 true|false
表4.6. Hibernate事务属性
属性名 用途 hibernate.transaction.factory_class 一个TransactionFactory 的类名, 用于Hibernate Transaction API (默认为JDBCTransactionFactory ).
取值 classname.of.TransactionFactory
jta.UserTransaction 一个JNDI名字,被JTATransactionFactory 用来从应用服务器获取JTA UserTransaction .
取值 jndi/composite/name
hibernate.transaction.manager_lookup_class 一个TransactionManagerLookup 的类名 - 当使用JVM级缓存,或在JTA环境中使用hilo生成器的时候需要该类.
取值 classname.of.TransactionManagerLookup
hibernate.transaction.flush_before_completion 如果开启, session在事务完成后将被自动清洗(flush). (在Hibernate和CMT一起使用时很有用.)
取值 true | false
hibernate.transaction.auto_close_session 如果开启, session在事务完成后将被自动关闭. (在Hibernate和CMT一起使用时很有用.)
取值 true | false
表4.7. 其他属性
属性名 用途 hibernate.query.factory_class 选择HQL解析器的实现.
取值 org.hibernate.hql.ast.ASTQueryTranslatorFactory or org.hibernate.hql.classic.ClassicQueryTranslatorFactory
hibernate.query.substitutions 将Hibernate查询中的符号映射到SQL查询中的符号 (符号可能是函数名或常量名字).
取值 hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC
hibernate.hbm2ddl.auto 在SessionFactory 创建时,自动将数据库schema的DDL导出到数据库. 使用 create-drop 时,在显式关闭SessionFactory 时,将drop掉数据库schema.
取值 update | create | create-drop
hibernate.cglib.use_reflection_optimizer 开启CGLIB来替代运行时反射机制(系统级属性). 反射机制有时在除错时比较有用. 注意即使关闭这个优化, Hibernate还是需要CGLIB. 你不能在hibernate.cfg.xml 中设置此属性.
取值 true | false
4.4.1. SQL方言
你应当总是为你的数据库属性hibernate.dialect 设置正确的 org.hibernate.dialect.Dialect 子类. 如果你指定一种方言, Hibernate将为上面列出的一些属性使用合理的默认值, 为你省去了手工指定它们的功夫.
表4.8. Hibernate SQL方言 (hibernate.dialect )
RDBMS 方言 DB2 org.hibernate.dialect.DB2Dialect DB2 AS/400 org.hibernate.dialect.DB2400Dialect DB2 OS390 org.hibernate.dialect.DB2390Dialect PostgreSQL org.hibernate.dialect.PostgreSQLDialect MySQL org.hibernate.dialect.MySQLDialect MySQL with InnoDB org.hibernate.dialect.MySQLInnoDBDialect MySQL with MyISAM org.hibernate.dialect.MySQLMyISAMDialect Oracle (any version) org.hibernate.dialect.OracleDialect Oracle 9i/10g org.hibernate.dialect.Oracle9Dialect Sybase org.hibernate.dialect.SybaseDialect Sybase Anywhere org.hibernate.dialect.SybaseAnywhereDialect Microsoft SQL Server org.hibernate.dialect.SQLServerDialect SAP DB org.hibernate.dialect.SAPDBDialect Informix org.hibernate.dialect.InformixDialect HypersonicSQL org.hibernate.dialect.HSQLDialect Ingres org.hibernate.dialect.IngresDialect Progress org.hibernate.dialect.ProgressDialect Mckoi SQL org.hibernate.dialect.MckoiDialect Interbase org.hibernate.dialect.InterbaseDialect Pointbase org.hibernate.dialect.PointbaseDialect FrontBase org.hibernate.dialect.FrontbaseDialect Firebird org.hibernate.dialect.FirebirdDialect
4.4.2. 外连接抓取(Outer Join Fetching)
如果你的数据库支持ANSI, Oracle或Sybase风格的外连接, 外连接抓取 常能通过限制往返数据库次数 (更多的工作交由数据库自己来完成)来提高效率. 外连接允许在单个SELECT SQL语句中, 通过many-to-one, one-to-many, many-to-many和one-to-one关联获取连接对象的整个对象图.
将hibernate.max_fetch_depth 设为0 能在全局 范围内禁止外连接抓取. 设为1 或更高值能启用one-to-one和many-to-oneouter关联的外连接抓取, 它们通过 fetch="join" 来映射.
参见第20.1节 “ 抓取策略(Fetching strategies) ” 获得更多信息.
4.4.3. 二进制流 (Binary Streams)
Oracle限制那些通过JDBC驱动传输的字节 数组的数目. 如果你希望使用二进值 (binary) 或 可序列化的 (serializable) 类型的大对象, 你应该开启 hibernate.jdbc.use_streams_for_binary 属性. 这是系统级属性.
4.4.4. 二级缓存与查询缓存
以hibernate.cache 为前缀的属性允许你在Hibernate中,使用进程或群集范围内的二级缓存系统. 参见第20.2节 “二级缓存(The Second Level Cache) ” 获取更多的详情.
4.4.5. 查询语言中的替换
你可以使用hibernate.query.substitutions 在Hibernate中定义新的查询符号. 例如:
hibernate.query.substitutions true=1, false=0将导致符号true 和false 在生成的SQL中被翻译成整数常量.
hibernate.query.substitutions toLowercase=LOWER将允许你重命名SQL中的LOWER 函数.
4.4.6. Hibernate的统计(statistics)机制
如果你开启hibernate.generate_statistics , 那么当你通过 SessionFactory.getStatistics() 调整正在运行的系统时,Hibernate将导出大量有用的数据. Hibernate甚至能被配置成通过JMX导出这些统计信息. 参考org.hibernate.stats 中接口的Javadoc,以获得更多信息.
4.5. 日志
Hibernate使用Apache commons-logging来为各种事件记录日志.
commons-logging将直接输出到Apache Log4j(如果在类路径中包括log4j.jar )或 JDK1.4 logging (如果运行在JDK1.4或以上的环境下). 你可以从http://jakarta.apache.org 下载Log4j. 要使用Log4j,你需要将log4j.properties 文件放置在类路径下, 随Hibernate 一同分发的样例属性文件在src/ 目录下.
我们强烈建议你熟悉一下Hibernate的日志消息. 在不失可读性的前提下, 我们做了很多工作,使Hibernate的日志可能地详细. 这是必要的查错利器. 最令人感兴趣的日志分类有如下这些:
表4.9. Hibernate日志类别
类别 功能 org.hibernate.SQL 在所有SQL DML语句被执行时为它们记录日志 org.hibernate.type 为所有JDBC参数记录日志 org.hibernate.tool.hbm2ddl 在所有SQL DDL语句执行时为它们记录日志 org.hibernate.pretty 在session清洗(flush)时,为所有与其关联的实体(最多20个)的状态记录日志 org.hibernate.cache 为所有二级缓存的活动记录日志 org.hibernate.transaction 为事务相关的活动记录日志 org.hibernate.jdbc 为所有JDBC资源的获取记录日志 org.hibernate.hql.ast 为HQL和SQL的自动状态转换和其他关于查询解析的信息记录日志 org.hibernate.secure 为JAAS认证请求做日志 org.hibernate 为任何Hibernate相关信息做日志 (信息量较大, 但对查错非常有帮助)
在使用Hibernate开发应用程序时, 你应当总是为org.hibernate.SQL 开启debug 级别的日志记录,或者开启hibernate.show_sql 属性来代替它。.
4.6. 实现NamingStrategy
org.hibernate.cfg.NamingStrategy 接口允许你为数据库中的对象和schema 元素指定一个“命名标准”.
你可能会提供一些通过Java标识生成数据库标识或将映射定义文件中"逻辑"表/列名处理成"物理"表/列名的规则. 这个特性有助于减少冗长的映射定义文件.
在加入映射定义前,你可以调用 Configuration.setNamingStrategy() 指定一个不同的命名策略:
SessionFactory sf = new Configuration()
.setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
.addFile("Item.hbm.xml")
.addFile("Bid.hbm.xml")
.buildSessionFactory();org.hibernate.cfg.ImprovedNamingStrategy 是一个内建的命名策略, 对 一些应用程序而言,可能是非常有用的起点.
4.7. XML配置文件
另一个配置方法是在hibernate.cfg.xml 文件中指定一套完整的配置. 这个文件可以当成hibernate.properties 的替代。 若两个文件同时存在,它将重载前者的属性.
XML配置文件被默认是放在CLASSPATH 的根目录下. 这是一个例子:
java:/comp/env/jdbc/MyDB
org.hibernate.dialect.MySQLDialect
false
org.hibernate.transaction.JTATransactionFactory
java:comp/UserTransaction
如你所见, 这个方法优势在于,在配置文件中指出了映射定义文件的名字. 一旦你需要调整Hibernate的缓存, hibernate.cfg.xml 也是更方便. 注意,使用hibernate.properties 还是 hibernate.cfg.xml 完全是由你来决定, 除了上面提到的XML语法的优势之外, 两者是等价的.
使用XML配置,使得启动Hibernate变的异常简单, 如下所示,一行代码就可以搞定:
SessionFactory sf = new Configuration().configure().buildSessionFactory();你可以使用如下代码来添加一个不同的XML配置文件
SessionFactory sf = new Configuration()
.configure("catdb.cfg.xml")
.buildSessionFactory();4.8. J2EE应用程序服务器的集成
针对J2EE体系,Hibernate有如下几个集成的方面:
容器管理的数据源(Container-managed datasources) : Hibernate能通过容器管理由JNDI提供的JDBC连接. 通常, 特别是当处理多个数据源的分布式事务的时候, 由一个JTA兼容的TransactionManager 和一个 ResourceManager 来处理事务管理(CMT, 容器管理的事务). 当然你可以通过 编程方式来划分事务边界(BMT, Bean管理的事务). 或者为了代码的可移植性,你也也许会想使用可选的 Hibernate Transaction API.
自动JNDI绑定 : Hibernate可以在启动后将 SessionFactory 绑定到JNDI.
JTA Session绑定: 如果使用EJB, Hibernate Session 可以自动绑定到JTA事务作用的范围. 只需简单地从JNDI查找SessionFactory 并获得当前的 Session . 当JTA事务完成时, 让Hibernate来处理 Session 的清洗(flush)与关闭. 在EJB的部署描述符中事务边界是声明式的.
JMX部署: 如果你使用支持JMX应用程序服务器(如, JBoss AS), 那么你可以选择将Hibernate部署成托管MBean. 这将为你省去一行从Configuration 构建SessionFactory 的启动代码. 容器将启动你的HibernateService , 并完美地处理好服务间的依赖关系 (在Hibernate启动前,数据源必须是可用的等等).
如果应用程序服务器抛出"connection containment"异常, 根据你的环境,也许该将配置属性 hibernate.connection.release_mode 设为after_statement .
4.8.1. 事务策略配置
在你的架构中,Hibernate的Session API是独立于任何事务分界系统的. 如果你让Hibernate通过连接池直接使用JDBC, 你需要调用JDBC API来打开和关闭你的事务. 如果你运行在J2EE应用程序服务器中, 你也许想用Bean管理的事务并在需要的时候调用JTA API和UserTransaction .
为了让你的代码在两种(或其他)环境中可以移植,我们建议使用可选的Hibernate Transaction API, 它包装并隐藏了底层系统. 你必须通过设置Hibernate配置属性hibernate.transaction.factory_class 来指定 一个Transaction 实例的工厂类.
存在着三个标准(内建)的选择:
org.hibernate.transaction.JDBCTransactionFactory
委托给数据库(JDBC)事务(默认)
org.hibernate.transaction.JTATransactionFactory
如果在上下文环境中存在运行着的事务(如, EJB会话Bean的方法), 则委托给容器管 理的事务, 否则,将启动一个新的事务,并使用Bean管理的事务.
org.hibernate.transaction.CMTTransactionFactory
委托给容器管理的JTA事务
你也可以定义属于你自己的事务策略 (如, 针对CORBA的事务服务)
Hibernate的一些特性 (即二级缓存, JTA与Session的自动绑定等等)需要访问在托管环境中的JTA TransactionManager . 由于J2EE没有标准化一个单一的机制,Hibernate在应用程序服务器中,你必须指定Hibernate如何获得TransactionManager 的引用:
表4.10.JTA TransactionManagers
Transaction工厂类 应用程序服务器 org.hibernate.transaction.JBossTransactionManagerLookup JBoss org.hibernate.transaction.WeblogicTransactionManagerLookup Weblogic org.hibernate.transaction.WebSphereTransactionManagerLookup WebSphere org.hibernate.transaction.WebSphereExtendedJTATransactionLookup WebSphere 6 org.hibernate.transaction.OrionTransactionManagerLookup Orion org.hibernate.transaction.ResinTransactionManagerLookup Resin org.hibernate.transaction.JOTMTransactionManagerLookup JOTM org.hibernate.transaction.JOnASTransactionManagerLookup JOnAS org.hibernate.transaction.JRun4TransactionManagerLookup JRun4 org.hibernate.transaction.BESTransactionManagerLookup Borland ES
4.8.2. JNDI绑定的SessionFactory
与JNDI绑定的Hibernate的SessionFactory 能简化工厂的查询,简化创建新的Session . 需要注意的是这与JNDI绑定Datasource 没有关系, 它们只是恰巧用了相同的注册表!
如果你希望将SessionFactory 绑定到一个JNDI的名字空间, 用属性hibernate.session_factory_name 指定一个名字(如, java:hibernate/SessionFactory ). 如果不设置这个属性, SessionFactory 将不会被绑定到JNDI中. (在以只读JNDI为默认实现的环境中,这个设置尤其有用, 如Tomcat.)
在将SessionFactory 绑定至JNDI时, Hibernate将使用hibernate.jndi.url , 和hibernate.jndi.class 的值来实例化初始环境(initial context). 如果它们没有被指定, 将使用默认的InitialContext .
在你调用cfg.buildSessionFactory() 后, Hibernate会自动将SessionFactory 注册到JNDI. 这意味这你至少需要在你应用程序的启动代码(或工具类)中完成这个调用, 除非你使用HibernateService 来做JMX部署 (见后面讨论).
如果你使用与JNDI绑定的SessionFactory , EJB或任何其他类可以通过一个JNDI查询来获得这个SessionFactory . 请注意, 如果你使用第一章中介绍的帮助类HibernateUtil - 类似Singleton(单实例)注册表, 那么这里的启动代码不是必要的. 但HibernateUtil 更多被使用在非托管环境中.
4.8.3. JTA和Session的自动绑定
在非托管环境中,我们建议:HibernateUtil 和静态SessionFactory 一起工作, 由ThreadLocal 管理Hibernate Session 。 由于一些EJB可能会运行在同一个事务但不同线程的环境中, 所以这个方法不能照搬到EJB环境中. 我们建议在托管环境中,将SessionFactory 绑定到JNDI上.
请使用SessionFactory 的getCurrentSession() 方法来代替 直接使用ThreadLocal 去获得Hibernate Session . 如果在当前JTA事务中没有Hibernate Session , 将会启动一个并将它关联到事务中. 对于使用getCurrentSession() 获得的每个Session 而言, hibernate.transaction.flush_before_completion 和hibernate.transaction.auto_close_session 这两个配置选项会自动设置, 因此在容器结束JTA事务时,这些Session 会被自动清洗(flush)并关闭.
例如,如果你使用DAO模式来编写你的持久层, 那么在需要时,所有DAO将查找SessionFactory 并打开"当前"Session. 没有必要在控制代码和DAO代码间传递SessionFactory 或Session 的实例.
4.8.4. JMX部署
为了将SessionFactory 注册到JNDI中cfg.buildSessionFactory() 这行代码仍需在某处被执行. 你可在一个static 初始化块(像HibernateUtil 中的那样)中执行它或将Hibernate部署为一个托管的服务 .
为了部署在一个支持JMX的应用程序服务器上,Hibernate和 org.hibernate.jmx.HibernateService 一同分发,如Jboss AS。 实际的部署和配置是由应用程序服务器提供者指定的. 这里是JBoss 4.0.x的jboss-service.xml 样例:
jboss.jca:service=RARDeployer
jboss.jca:service=LocalTxCM,name=HsqlDS
java:/hibernate/SessionFactory
java:HsqlDS
org.hibernate.dialect.HSQLDialect
org.hibernate.transaction.JTATransactionFactory
org.hibernate.transaction.JBossTransactionManagerLookup
true
true
5
true
org.hibernate.cache.EhCacheProvider
true
true
auction/Item.hbm.xml,auction/Category.hbm.xml
这个文件是部署在META-INF 目录下的, 并会被打包到以.sar (service archive)为扩展名的JAR文件中. 同时,你需要打包Hibernate, 它所需要的第三方库, 你编译好的持久化类及你的映射定义文件打包进同一个文档. 你的企业Bean(一般为会话Bean)可能会被打包成它们自己的JAR文件, 但你也许会将EJB JAR文件一同包含进能独立(热)部署的主服务文档. 咨询JBoss AS文档以了解更多的JMX服务与EJB部署的信息.