【永恒的瞬間】
          ?Give me hapy ?

          第 4 章  配置

          由于Hibernate是為了能在各種不同環(huán)境下工作而設(shè)計(jì)的, 因此存在著大量的配置參數(shù). 幸運(yùn)的是多數(shù)配置參數(shù)都 有比較直觀的默認(rèn)值, 并有隨Hibernate一同分發(fā)的配置樣例hibernate.properties (位于etc/)來(lái)展示各種配置選項(xiàng). 所需做的僅僅是將這個(gè)樣例文件復(fù)制到類路徑 (classpath)下做一些自定義的修改.

          4.1.  可編程的配置方式

          一個(gè)org.hibernate.cfg.Configuration實(shí)例代表了一個(gè)應(yīng)用程序中Java類型 到SQL數(shù)據(jù)庫(kù)映射的完整集合. Configuration被用來(lái)構(gòu)建一個(gè)(不可變的 (immutable))SessionFactory. 映射定義則由不同的XML映射定義文件編譯而來(lái).

          你可以直接實(shí)例化Configuration來(lái)獲取一個(gè)實(shí)例,并為它指定XML映射定義 文件. 如果映射定 義文件在類路徑(classpath)中, 請(qǐng)使用addResource():

          Configuration cfg = new Configuration()
          .addResource("Item.hbm.xml")
          .addResource("Bid.hbm.xml");

          一個(gè)替代方法(有時(shí)是更好的選擇)是,指定被映射的類,讓Hibernate幫你尋找映射定義文件:

          Configuration cfg = new Configuration()
          .addClass(org.hibernate.auction.Item.class)
          .addClass(org.hibernate.auction.Bid.class);

          Hibernate將會(huì)在類路徑(classpath)中尋找名字為 /org/hibernate/auction/Item.hbm.xml/org/hibernate/auction/Bid.hbm.xml映射定義文件. 這種方式消除了任何對(duì)文件名的硬編碼(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");

          當(dāng)然這不是唯一的傳遞Hibernate配置屬性的方式, 其他可選方式還包括:

          1. 傳一個(gè)java.util.Properties實(shí)例給 Configuration.setProperties().

          2. hibernate.properties放置在類路徑(classpath)的根目錄下 (root directory).

          3. 通過(guò)java -Dproperty=value來(lái)設(shè)置系統(tǒng) (System)屬性.

          4. hibernate.cfg.xml中加入元素 <property> (稍后討論).

          如果想盡快體驗(yàn)Hbernate, hibernate.properties是最簡(jiǎn)單的方式.

          Configuration實(shí)例是一個(gè)啟動(dòng)期間(startup-time)的對(duì)象, 一旦SessionFactory創(chuàng)建完成它就被丟棄了.

          4.2.  獲得SessionFactory

          當(dāng)所有映射定義被Configuration解析后, 應(yīng)用程序必須獲得一個(gè)用于構(gòu)造Session實(shí)例的工廠. 這個(gè)工廠將被應(yīng)用程序的所有線程共享:

          SessionFactory sessions = cfg.buildSessionFactory();

          Hibernate允許你的應(yīng)用程序創(chuàng)建多個(gè)SessionFactory實(shí)例. 這對(duì) 使用多個(gè)數(shù)據(jù)庫(kù)的應(yīng)用來(lái)說(shuō)很有用.

          4.3.  JDBC連接

          通常你希望SessionFactory來(lái)為你創(chuàng)建和緩存(pool)JDBC連接. 如果你采用這種方式, 只需要如下例所示那樣,打開(kāi)一個(gè)Session:

          Session session = sessions.openSession(); // open a new Session

          一旦你需要進(jìn)行數(shù)據(jù)訪問(wèn)時(shí), 就會(huì)從連接池(connection pool)獲得一個(gè)JDBC連接.

          為了使這種方式工作起來(lái), 我們需要向Hibernate傳遞一些JDBC連接的屬性. 所有Hibernate屬性的名字和語(yǔ)義都在org.hibernate.cfg.Environment中定義. 我們現(xiàn)在將描述JDBC連接配置中最重要的設(shè)置.

          如果你設(shè)置如下屬性,Hibernate將使用java.sql.DriverManager來(lái)獲得(和緩存)JDBC連接 :

          表 4.1.  Hibernate JDBC屬性

          屬性名 用途
          hibernate.connection.driver_class jdbc驅(qū)動(dòng)類
          hibernate.connection.url jdbc URL
          hibernate.connection.username 數(shù)據(jù)庫(kù)用戶
          hibernate.connection.password 數(shù)據(jù)庫(kù)用戶密碼
          hibernate.connection.pool_size 連接池容量上限數(shù)目

          但Hibernate自帶的連接池算法相當(dāng)不成熟. 它只是為了讓你快些上手,不適合用于產(chǎn)品系統(tǒng)或性能測(cè)試中。 出于最佳性能和穩(wěn)定性考慮你應(yīng)該使用第三方的連接池。只需要連接池的特定設(shè)置替換 hibernate.connection.pool_size。這將關(guān)閉Hibernate自帶的連接池. 例如, 你可能會(huì)想用C3P0.

          C3P0是一個(gè)隨Hibernate一同分發(fā)的開(kāi)源的JDBC連接池, 它位于lib目錄下。 如果你設(shè)置了hibernate.c3p0.*相關(guān)的屬性, Hibernate將使用 C3P0ConnectionProvider來(lái)緩存JDBC連接. 如果你更原意使用Proxool, 請(qǐng)參考發(fā) 行包中的hibernate.properties并到Hibernate網(wǎng)站獲取更多的信息.

          這是一個(gè)使用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

          為了能在應(yīng)用程序服務(wù)器(application server)中使用Hibernate, 你應(yīng)當(dāng)總是將Hibernate 配置成注冊(cè)在JNDI中的Datasource處獲得連接,你至少需要設(shè)置下列屬性中的一個(gè):

          表 4.2.  Hibernate數(shù)據(jù)源屬性

          屬性名 用途
          hibernate.connection.datasource 數(shù)據(jù)源JNDI名字
          hibernate.jndi.url JNDI提供者的URL (可選)
          hibernate.jndi.class JNDI InitialContextFactory (可選)
          hibernate.connection.username 數(shù)據(jù)庫(kù)用戶 (可選)
          hibernate.connection.password 數(shù)據(jù)庫(kù)用戶密碼 (可選)

          這里有一個(gè)使用應(yīng)用程序服務(wù)器JNDI數(shù)據(jù)源的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數(shù)據(jù)源獲得的JDBC連接將自動(dòng)參與應(yīng)用程序服務(wù)器中容器管理的事務(wù)(container-managed transactions)中去.

          任何連接(connection)配置屬性的屬性名要以"hibernate.connnection"前綴開(kāi)頭. 例如, 你可能會(huì)使用hibernate.connection.charSet來(lái)指定charSet.

          通過(guò)實(shí)現(xiàn)org.hibernate.connection.ConnectionProvider接口,你可以定義屬于 你自己的獲得JDBC連接的插件策略。通過(guò)設(shè)置hibernate.connection.provider_class, 你可以選擇一個(gè)自定義的實(shí)現(xiàn).

          4.4.  可選的配置屬性

          有大量屬性能用來(lái)控制Hibernate在運(yùn)行期的行為. 它們都是可選的, 并擁有適當(dāng)?shù)哪J(rèn)值.

          警告: 其中一些屬性是"系統(tǒng)級(jí)(system-level)的". 系統(tǒng)級(jí)屬性可以通過(guò)java -Dproperty=valuehibernate.properties來(lái)設(shè)置, 而不能用上面描述的其他方法來(lái)設(shè)置.

          表 4.3.  Hibernate配置屬性

          屬性名 用途
          hibernate.dialect 一個(gè)Hibernate Dialect類名允許Hibernate針對(duì)特定的關(guān)系數(shù)據(jù)庫(kù)生成優(yōu)化的SQL.

          取值 full.classname.of.Dialect

          hibernate.show_sql 輸出所有SQL語(yǔ)句到控制臺(tái).

          取值 true | false

          hibernate.default_schema 在生成的SQL中, 將給定的schema/tablespace附加于非全限定名的表名上.

          取值 SCHEMA_NAME

          hibernate.default_catalog 在生成的SQL中, 將給定的catalog附加于沒(méi)全限定名的表名上.

          取值 CATALOG_NAME

          hibernate.session_factory_name SessionFactory創(chuàng)建后,將自動(dòng)使用這個(gè)名字綁定到JNDI中.

          取值 jndi/composite/name

          hibernate.max_fetch_depth 為單向關(guān)聯(lián)(一對(duì)一, 多對(duì)一)的外連接抓取(outer join fetch)樹(shù)設(shè)置最大深度. 值為0意味著將關(guān)閉默認(rèn)的外連接抓取.

          取值 建議在03之間取值

          hibernate.default_batch_fetch_size 為Hibernate關(guān)聯(lián)的批量抓取設(shè)置默認(rèn)數(shù)量.

          取值 建議的取值為4, 8, 和16

          hibernate.default_entity_mode 為由這個(gè)SessionFactory打開(kāi)的所有Session指定默認(rèn)的實(shí)體表現(xiàn)模式.

          取值 dynamic-map, dom4j, pojo

          hibernate.order_updates 強(qiáng)制Hibernate按照被更新數(shù)據(jù)的主鍵,為SQL更新排序。這么做將減少在高并發(fā)系統(tǒng)中事務(wù)的死鎖。

          取值 true | false

          hibernate.generate_statistics 如果開(kāi)啟, Hibernate將收集有助于性能調(diào)節(jié)的統(tǒng)計(jì)數(shù)據(jù).

          取值 true | false

          hibernate.use_identifer_rollback 如果開(kāi)啟, 在對(duì)象被刪除時(shí)生成的標(biāo)識(shí)屬性將被重設(shè)為默認(rèn)值.

          取值 true | false

          hibernate.use_sql_comments 如果開(kāi)啟, Hibernate將在SQL中生成有助于調(diào)試的注釋信息, 默認(rèn)值為false.

          取值 true | false

          表 4.4.  Hibernate JDBC和連接(connection)屬性

          屬性名 用途
          hibernate.jdbc.fetch_size 非零值,指定JDBC抓取數(shù)量的大小 (調(diào)用Statement.setFetchSize()).
          hibernate.jdbc.batch_size 非零值,允許Hibernate使用JDBC2的批量更新.

          取值 建議取530之間的值

          hibernate.jdbc.batch_versioned_data 如果你想讓你的JDBC驅(qū)動(dòng)從executeBatch()返回正確的行計(jì)數(shù) , 那么將此屬性設(shè)為true(開(kāi)啟這個(gè)選項(xiàng)通常是安全的). 同時(shí),Hibernate將為自動(dòng)版本化的數(shù)據(jù)使用批量DML. 默認(rèn)值為false.

          eg. true | false

          hibernate.jdbc.factory_class 選擇一個(gè)自定義的Batcher. 多數(shù)應(yīng)用程序不需要這個(gè)配置屬性.

          eg. classname.of.Batcher

          hibernate.jdbc.use_scrollable_resultset 允許Hibernate使用JDBC2的可滾動(dòng)結(jié)果集. 只有在使用用戶提供的JDBC連接時(shí),這個(gè)選項(xiàng)才是必要的, 否則Hibernate會(huì)使用連接的元數(shù)據(jù).

          取值 true | false

          hibernate.jdbc.use_streams_for_binary 在JDBC讀寫binary (二進(jìn)制)serializable (可序列化) 的類型時(shí)使用流(stream)(系統(tǒng)級(jí)屬性).

          取值 true | false

          hibernate.jdbc.use_get_generated_keys 在數(shù)據(jù)插入數(shù)據(jù)庫(kù)之后,允許使用JDBC3 PreparedStatement.getGeneratedKeys() 來(lái)獲取數(shù)據(jù)庫(kù)生成的key(鍵)。需要JDBC3+驅(qū)動(dòng)和JRE1.4+, 如果你的數(shù)據(jù)庫(kù)驅(qū)動(dòng)在使用Hibernate的標(biāo) 識(shí)生成器時(shí)遇到問(wèn)題,請(qǐng)將此值設(shè)為false. 默認(rèn)情況下將使用連接的元數(shù)據(jù)來(lái)判定驅(qū)動(dòng)的能力.

          取值 true|false

          hibernate.connection.provider_class 自定義ConnectionProvider的類名, 此類用來(lái)向Hibernate提供JDBC連接.

          取值 classname.of.ConnectionProvider

          hibernate.connection.isolation 設(shè)置JDBC事務(wù)隔離級(jí)別. 查看java.sql.Connection來(lái)了解各個(gè)值的具體意義, 但請(qǐng)注意多數(shù)數(shù)據(jù)庫(kù)都不支持所有的隔離級(jí)別.

          取值 1, 2, 4, 8

          hibernate.connection.autocommit 允許被緩存的JDBC連接開(kāi)啟自動(dòng)提交(autocommit) (不建議).

          取值 true | false

          hibernate.connection.release_mode 指定Hibernate在何時(shí)釋放JDBC連接. 默認(rèn)情況下,直到Session被顯式關(guān)閉或被斷開(kāi)連接時(shí),才會(huì)釋放JDBC連接. 對(duì)于應(yīng)用程序服務(wù)器的JTA數(shù)據(jù)源, 你應(yīng)當(dāng)使用after_statement, 這樣在每次JDBC調(diào)用后,都會(huì)主動(dòng)的釋放連接. 對(duì)于非JTA的連接, 使用after_transaction在每個(gè)事務(wù)結(jié)束時(shí)釋放連接是合理的. auto將為JTA和CMT事務(wù)策略選擇after_statement, 為JDBC事務(wù)策略選擇after_transaction.

          取值 on_close | after_transaction | after_statement | auto

          hibernate.connection.<propertyName> 將JDBC屬性propertyName傳遞到DriverManager.getConnection()中去.
          hibernate.jndi.<propertyName> 將屬性propertyName傳遞到JNDI InitialContextFactory中去.

          表 4.5.  Hibernate緩存屬性

          屬性名 用途
          hibernate.cache.provider_class 自定義的CacheProvider的類名.

          取值 classname.of.CacheProvider

          hibernate.cache.use_minimal_puts 以頻繁的讀操作為代價(jià), 優(yōu)化二級(jí)緩存來(lái)最小化寫操作. 在Hibernate3中,這個(gè)設(shè)置對(duì)的集群緩存非常有用, 對(duì)集群緩存的實(shí)現(xiàn)而言,默認(rèn)是開(kāi)啟的.

          取值 true|false

          hibernate.cache.use_query_cache 允許查詢緩存, 個(gè)別查詢?nèi)匀恍枰辉O(shè)置為可緩存的.

          取值 true|false

          hibernate.cache.use_second_level_cache 能用來(lái)完全禁止使用二級(jí)緩存. 對(duì)那些在類的映射定義中指定<cache>的類,會(huì)默認(rèn)開(kāi)啟二級(jí)緩存.

          取值 true|false

          hibernate.cache.query_cache_factory 自定義的實(shí)現(xiàn)QueryCache接口的類名, 默認(rèn)為內(nèi)建的StandardQueryCache.

          取值 classname.of.QueryCache

          hibernate.cache.region_prefix 二級(jí)緩存區(qū)域名的前綴.

          取值 prefix

          hibernate.cache.use_structured_entries 強(qiáng)制Hibernate以更人性化的格式將數(shù)據(jù)存入二級(jí)緩存.

          取值 true|false

          表 4.6.  Hibernate事務(wù)屬性

          屬性名 用途
          hibernate.transaction.factory_class 一個(gè)TransactionFactory的類名, 用于Hibernate Transaction API (默認(rèn)為JDBCTransactionFactory).

          取值 classname.of.TransactionFactory

          jta.UserTransaction 一個(gè)JNDI名字,被JTATransactionFactory用來(lái)從應(yīng)用服務(wù)器獲取JTA UserTransaction.

          取值 jndi/composite/name

          hibernate.transaction.manager_lookup_class 一個(gè)TransactionManagerLookup的類名 - 當(dāng)使用JVM級(jí)緩存,或在JTA環(huán)境中使用hilo生成器的時(shí)候需要該類.

          取值 classname.of.TransactionManagerLookup

          hibernate.transaction.flush_before_completion 如果開(kāi)啟, session在事務(wù)完成后將被自動(dòng)清洗(flush). (在Hibernate和CMT一起使用時(shí)很有用.)

          取值 true | false

          hibernate.transaction.auto_close_session 如果開(kāi)啟, session在事務(wù)完成后將被自動(dòng)關(guān)閉. (在Hibernate和CMT一起使用時(shí)很有用.)

          取值 true | false

          表 4.7.  其他屬性

          屬性名 用途
          hibernate.query.factory_class 選擇HQL解析器的實(shí)現(xiàn).

          取值 org.hibernate.hql.ast.ASTQueryTranslatorFactory or org.hibernate.hql.classic.ClassicQueryTranslatorFactory

          hibernate.query.substitutions 將Hibernate查詢中的符號(hào)映射到SQL查詢中的符號(hào) (符號(hào)可能是函數(shù)名或常量名字).

          取值 hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC

          hibernate.hbm2ddl.auto SessionFactory創(chuàng)建時(shí),自動(dòng)將數(shù)據(jù)庫(kù)schema的DDL導(dǎo)出到數(shù)據(jù)庫(kù). 使用 create-drop時(shí),在顯式關(guān)閉SessionFactory時(shí),將drop掉數(shù)據(jù)庫(kù)schema.

          取值 update | create | create-drop

          hibernate.cglib.use_reflection_optimizer 開(kāi)啟CGLIB來(lái)替代運(yùn)行時(shí)反射機(jī)制(系統(tǒng)級(jí)屬性). 反射機(jī)制有時(shí)在除錯(cuò)時(shí)比較有用. 注意即使關(guān)閉這個(gè)優(yōu)化, Hibernate還是需要CGLIB. 你不能在hibernate.cfg.xml中設(shè)置此屬性.

          取值 true | false

          4.4.1.  SQL方言

          你應(yīng)當(dāng)總是為你的數(shù)據(jù)庫(kù)屬性hibernate.dialect設(shè)置正確的 org.hibernate.dialect.Dialect子類. 如果你指定一種方言, Hibernate將為上面列出的一些屬性使用合理的默認(rèn)值, 為你省去了手工指定它們的功夫.

          表 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)

          如果你的數(shù)據(jù)庫(kù)支持ANSI, Oracle或Sybase風(fēng)格的外連接, 外連接抓取常能通過(guò)限制往返數(shù)據(jù)庫(kù)次數(shù) (更多的工作交由數(shù)據(jù)庫(kù)自己來(lái)完成)來(lái)提高效率. 外連接允許在單個(gè)SELECTSQL語(yǔ)句中, 通過(guò)many-to-one, one-to-many, many-to-many和one-to-one關(guān)聯(lián)獲取連接對(duì)象的整個(gè)對(duì)象圖.

          hibernate.max_fetch_depth設(shè)為0能在全局 范圍內(nèi)禁止外連接抓取. 設(shè)為1或更高值能啟用one-to-one和many-to-oneouter關(guān)聯(lián)的外連接抓取, 它們通過(guò) fetch="join"來(lái)映射.

          參見(jiàn)第 20.1 節(jié) “ 抓取策略(Fetching strategies) ”獲得更多信息.

          4.4.3.  二進(jìn)制流 (Binary Streams)

          Oracle限制那些通過(guò)JDBC驅(qū)動(dòng)傳輸?shù)?tt class=literal>字節(jié)數(shù)組的數(shù)目. 如果你希望使用二進(jìn)值 (binary)可序列化的 (serializable)類型的大對(duì)象, 你應(yīng)該開(kāi)啟 hibernate.jdbc.use_streams_for_binary屬性. 這是系統(tǒng)級(jí)屬性.

          4.4.4.  二級(jí)緩存與查詢緩存

          hibernate.cache為前綴的屬性允許你在Hibernate中,使用進(jìn)程或群集范圍內(nèi)的二級(jí)緩存系統(tǒng). 參見(jiàn)第 20.2 節(jié) “二級(jí)緩存(The Second Level Cache) ”獲取更多的詳情.

          4.4.5.  查詢語(yǔ)言中的替換

          你可以使用hibernate.query.substitutions在Hibernate中定義新的查詢符號(hào). 例如:

          hibernate.query.substitutions true=1, false=0

          將導(dǎo)致符號(hào)truefalse在生成的SQL中被翻譯成整數(shù)常量.

          hibernate.query.substitutions toLowercase=LOWER

          將允許你重命名SQL中的LOWER函數(shù).

          4.4.6.  Hibernate的統(tǒng)計(jì)(statistics)機(jī)制

          如果你開(kāi)啟hibernate.generate_statistics, 那么當(dāng)你通過(guò) SessionFactory.getStatistics()調(diào)整正在運(yùn)行的系統(tǒng)時(shí),Hibernate將導(dǎo)出大量有用的數(shù)據(jù). Hibernate甚至能被配置成通過(guò)JMX導(dǎo)出這些統(tǒng)計(jì)信息. 參考org.hibernate.stats中接口的Javadoc,以獲得更多信息.

          4.5.  日志

          Hibernate使用Apache commons-logging來(lái)為各種事件記錄日志.

          commons-logging將直接輸出到Apache Log4j(如果在類路徑中包括log4j.jar)或 JDK1.4 logging (如果運(yùn)行在JDK1.4或以上的環(huán)境下). 你可以從http://jakarta.apache.org 下載Log4j. 要使用Log4j,你需要將log4j.properties文件放置在類路徑下, 隨Hibernate 一同分發(fā)的樣例屬性文件在src/目錄下.

          我們強(qiáng)烈建議你熟悉一下Hibernate的日志消息. 在不失可讀性的前提下, 我們做了很多工作,使Hibernate的日志可能地詳細(xì). 這是必要的查錯(cuò)利器. 最令人感興趣的日志分類有如下這些:

          表 4.9.  Hibernate日志類別

          類別 功能
          org.hibernate.SQL 在所有SQL DML語(yǔ)句被執(zhí)行時(shí)為它們記錄日志
          org.hibernate.type 為所有JDBC參數(shù)記錄日志
          org.hibernate.tool.hbm2ddl 在所有SQL DDL語(yǔ)句執(zhí)行時(shí)為它們記錄日志
          org.hibernate.pretty 在session清洗(flush)時(shí),為所有與其關(guān)聯(lián)的實(shí)體(最多20個(gè))的狀態(tài)記錄日志
          org.hibernate.cache 為所有二級(jí)緩存的活動(dòng)記錄日志
          org.hibernate.transaction 為事務(wù)相關(guān)的活動(dòng)記錄日志
          org.hibernate.jdbc 為所有JDBC資源的獲取記錄日志
          org.hibernate.hql.ast 為HQL和SQL的自動(dòng)狀態(tài)轉(zhuǎn)換和其他關(guān)于查詢解析的信息記錄日志
          org.hibernate.secure 為JAAS認(rèn)證請(qǐng)求做日志
          org.hibernate 為任何Hibernate相關(guān)信息做日志 (信息量較大, 但對(duì)查錯(cuò)非常有幫助)

          在使用Hibernate開(kāi)發(fā)應(yīng)用程序時(shí), 你應(yīng)當(dāng)總是為org.hibernate.SQL 開(kāi)啟debug級(jí)別的日志記錄,或者開(kāi)啟hibernate.show_sql屬性來(lái)代替它。.

          4.6.  實(shí)現(xiàn)NamingStrategy

          org.hibernate.cfg.NamingStrategy接口允許你為數(shù)據(jù)庫(kù)中的對(duì)象和schema 元素指定一個(gè)“命名標(biāo)準(zhǔn)”.

          你可能會(huì)提供一些通過(guò)Java標(biāo)識(shí)生成數(shù)據(jù)庫(kù)標(biāo)識(shí)或?qū)⒂成涠x文件中"邏輯"表/列名處理成"物理"表/列名的規(guī)則. 這個(gè)特性有助于減少冗長(zhǎng)的映射定義文件.

          在加入映射定義前,你可以調(diào)用 Configuration.setNamingStrategy()指定一個(gè)不同的命名策略:

          SessionFactory sf = new Configuration()
          .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)
          .addFile("Item.hbm.xml")
          .addFile("Bid.hbm.xml")
          .buildSessionFactory();

          org.hibernate.cfg.ImprovedNamingStrategy是一個(gè)內(nèi)建的命名策略, 對(duì) 一些應(yīng)用程序而言,可能是非常有用的起點(diǎn).

          4.7.  XML配置文件

          另一個(gè)配置方法是在hibernate.cfg.xml文件中指定一套完整的配置. 這個(gè)文件可以當(dāng)成hibernate.properties的替代。 若兩個(gè)文件同時(shí)存在,它將重載前者的屬性.

          XML配置文件被默認(rèn)是放在CLASSPATH的根目錄下. 這是一個(gè)例子:

           

          <?xml version='1.0' encoding='utf-8'?>
          <!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
          <hibernate-configuration>
          <!-- 以/jndi/name綁定到JNDI的SessionFactory實(shí)例 -->
          <session-factory
          name="java:hibernate/SessionFactory">
          <!-- 屬性 -->
          <property name="connection.datasource">java:/comp/env/jdbc/MyDB</property>
          <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
          <property name="show_sql">false</property>
          <property name="transaction.factory_class">
          org.hibernate.transaction.JTATransactionFactory
          </property>
          <property name="jta.UserTransaction">java:comp/UserTransaction</property>
          <!-- 映射定義文件 -->
          <mapping resource="org/hibernate/auction/Item.hbm.xml"/>
          <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>
          <!-- 緩存設(shè)置 -->
          <class-cache class="org.hibernate.auction.Item" usage="read-write"/>
          <class-cache class="org.hibernate.auction.Bid" usage="read-only"/>
          <collection-cache class="org.hibernate.auction.Item.bids" usage="read-write"/>
          </session-factory>
          </hibernate-configuration>

          如你所見(jiàn), 這個(gè)方法優(yōu)勢(shì)在于,在配置文件中指出了映射定義文件的名字. 一旦你需要調(diào)整Hibernate的緩存, hibernate.cfg.xml也是更方便. 注意,使用hibernate.properties還是 hibernate.cfg.xml完全是由你來(lái)決定, 除了上面提到的XML語(yǔ)法的優(yōu)勢(shì)之外, 兩者是等價(jià)的.

          使用XML配置,使得啟動(dòng)Hibernate變的異常簡(jiǎn)單, 如下所示,一行代碼就可以搞定:

          SessionFactory sf = new Configuration().configure().buildSessionFactory();

          你可以使用如下代碼來(lái)添加一個(gè)不同的XML配置文件

          SessionFactory sf = new Configuration()
          .configure("catdb.cfg.xml")
          .buildSessionFactory();

          4.8.  J2EE應(yīng)用程序服務(wù)器的集成

          針對(duì)J2EE體系,Hibernate有如下幾個(gè)集成的方面:

          • 容器管理的數(shù)據(jù)源(Container-managed datasources): Hibernate能通過(guò)容器管理由JNDI提供的JDBC連接. 通常, 特別是當(dāng)處理多個(gè)數(shù)據(jù)源的分布式事務(wù)的時(shí)候, 由一個(gè)JTA兼容的TransactionManager和一個(gè) ResourceManager來(lái)處理事務(wù)管理(CMT, 容器管理的事務(wù)). 當(dāng)然你可以通過(guò) 編程方式來(lái)劃分事務(wù)邊界(BMT, Bean管理的事務(wù)). 或者為了代碼的可移植性,你也也許會(huì)想使用可選的 Hibernate Transaction API.

          • 自動(dòng)JNDI綁定: Hibernate可以在啟動(dòng)后將 SessionFactory綁定到JNDI.

          • JTA Session綁定: 如果使用EJB, Hibernate Session 可以自動(dòng)綁定到JTA事務(wù)作用的范圍. 只需簡(jiǎn)單地從JNDI查找SessionFactory并獲得當(dāng)前的 Session. 當(dāng)JTA事務(wù)完成時(shí), 讓Hibernate來(lái)處理 Session的清洗(flush)與關(guān)閉. 在EJB的部署描述符中事務(wù)邊界是聲明式的.

          • JMX部署: 如果你使用支持JMX應(yīng)用程序服務(wù)器(如, JBoss AS), 那么你可以選擇將Hibernate部署成托管MBean. 這將為你省去一行從Configuration構(gòu)建SessionFactory的啟動(dòng)代碼. 容器將啟動(dòng)你的HibernateService, 并完美地處理好服務(wù)間的依賴關(guān)系 (在Hibernate啟動(dòng)前,數(shù)據(jù)源必須是可用的等等).

          如果應(yīng)用程序服務(wù)器拋出"connection containment"異常, 根據(jù)你的環(huán)境,也許該將配置屬性 hibernate.connection.release_mode設(shè)為after_statement.

          4.8.1.  事務(wù)策略配置

          在你的架構(gòu)中,Hibernate的Session API是獨(dú)立于任何事務(wù)分界系統(tǒng)的. 如果你讓Hibernate通過(guò)連接池直接使用JDBC, 你需要調(diào)用JDBC API來(lái)打開(kāi)和關(guān)閉你的事務(wù). 如果你運(yùn)行在J2EE應(yīng)用程序服務(wù)器中, 你也許想用Bean管理的事務(wù)并在需要的時(shí)候調(diào)用JTA API和UserTransaction.

          為了讓你的代碼在兩種(或其他)環(huán)境中可以移植,我們建議使用可選的Hibernate Transaction API, 它包裝并隱藏了底層系統(tǒng). 你必須通過(guò)設(shè)置Hibernate配置屬性hibernate.transaction.factory_class來(lái)指定 一個(gè)Transaction實(shí)例的工廠類.

          存在著三個(gè)標(biāo)準(zhǔn)(內(nèi)建)的選擇:

          org.hibernate.transaction.JDBCTransactionFactory

          委托給數(shù)據(jù)庫(kù)(JDBC)事務(wù)(默認(rèn))

          org.hibernate.transaction.JTATransactionFactory

          如果在上下文環(huán)境中存在運(yùn)行著的事務(wù)(如, EJB會(huì)話Bean的方法), 則委托給容器管 理的事務(wù), 否則,將啟動(dòng)一個(gè)新的事務(wù),并使用Bean管理的事務(wù).

          org.hibernate.transaction.CMTTransactionFactory

          委托給容器管理的JTA事務(wù)

          你也可以定義屬于你自己的事務(wù)策略 (如, 針對(duì)CORBA的事務(wù)服務(wù))

          Hibernate的一些特性 (即二級(jí)緩存, JTA與Session的自動(dòng)綁定等等)需要訪問(wèn)在托管環(huán)境中的JTA TransactionManager. 由于J2EE沒(méi)有標(biāo)準(zhǔn)化一個(gè)單一的機(jī)制,Hibernate在應(yīng)用程序服務(wù)器中,你必須指定Hibernate如何獲得TransactionManager的引用:

          表 4.10. JTA TransactionManagers

          Transaction工廠類 應(yīng)用程序服務(wù)器
          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能簡(jiǎn)化工廠的查詢,簡(jiǎn)化創(chuàng)建新的Session. 需要注意的是這與JNDI綁定Datasource沒(méi)有關(guān)系, 它們只是恰巧用了相同的注冊(cè)表!

          如果你希望將SessionFactory綁定到一個(gè)JNDI的名字空間, 用屬性hibernate.session_factory_name指定一個(gè)名字(如, java:hibernate/SessionFactory). 如果不設(shè)置這個(gè)屬性, SessionFactory將不會(huì)被綁定到JNDI中. (在以只讀JNDI為默認(rèn)實(shí)現(xiàn)的環(huán)境中,這個(gè)設(shè)置尤其有用, 如Tomcat.)

          在將SessionFactory綁定至JNDI時(shí), Hibernate將使用hibernate.jndi.url, 和hibernate.jndi.class的值來(lái)實(shí)例化初始環(huán)境(initial context). 如果它們沒(méi)有被指定, 將使用默認(rèn)的InitialContext.

          在你調(diào)用cfg.buildSessionFactory()后, Hibernate會(huì)自動(dòng)將SessionFactory注冊(cè)到JNDI. 這意味這你至少需要在你應(yīng)用程序的啟動(dòng)代碼(或工具類)中完成這個(gè)調(diào)用, 除非你使用HibernateService來(lái)做JMX部署 (見(jiàn)后面討論).

          如果你使用與JNDI綁定的SessionFactory, EJB或任何其他類可以通過(guò)一個(gè)JNDI查詢來(lái)獲得這個(gè)SessionFactory. 請(qǐng)注意, 如果你使用第一章中介紹的幫助類HibernateUtil - 類似Singleton(單實(shí)例)注冊(cè)表, 那么這里的啟動(dòng)代碼不是必要的. 但HibernateUtil更多被使用在非托管環(huán)境中.

          4.8.3.  JTA和Session的自動(dòng)綁定

          在非托管環(huán)境中,我們建議:HibernateUtil和靜態(tài)SessionFactory一起工作, 由ThreadLocal管理Hibernate Session。 由于一些EJB可能會(huì)運(yùn)行在同一個(gè)事務(wù)但不同線程的環(huán)境中, 所以這個(gè)方法不能照搬到EJB環(huán)境中. 我們建議在托管環(huán)境中,將SessionFactory綁定到JNDI上.

          請(qǐng)使用SessionFactorygetCurrentSession()方法來(lái)代替 直接使用ThreadLocal去獲得Hibernate Session. 如果在當(dāng)前JTA事務(wù)中沒(méi)有Hibernate Session, 將會(huì)啟動(dòng)一個(gè)并將它關(guān)聯(lián)到事務(wù)中. 對(duì)于使用getCurrentSession()獲得的每個(gè)Session而言, hibernate.transaction.flush_before_completionhibernate.transaction.auto_close_session這兩個(gè)配置選項(xiàng)會(huì)自動(dòng)設(shè)置, 因此在容器結(jié)束JTA事務(wù)時(shí),這些Session會(huì)被自動(dòng)清洗(flush)并關(guān)閉.

          例如,如果你使用DAO模式來(lái)編寫你的持久層, 那么在需要時(shí),所有DAO將查找SessionFactory并打開(kāi)"當(dāng)前"Session. 沒(méi)有必要在控制代碼和DAO代碼間傳遞SessionFactorySession的實(shí)例.

          4.8.4.  JMX部署

          為了將SessionFactory注冊(cè)到JNDI中cfg.buildSessionFactory()這行代碼仍需在某處被執(zhí)行. 你可在一個(gè)static初始化塊(像HibernateUtil中的那樣)中執(zhí)行它或?qū)ibernate部署為一個(gè)托管的服務(wù).

          為了部署在一個(gè)支持JMX的應(yīng)用程序服務(wù)器上,Hibernate和 org.hibernate.jmx.HibernateService一同分發(fā),如Jboss AS。 實(shí)際的部署和配置是由應(yīng)用程序服務(wù)器提供者指定的. 這里是JBoss 4.0.x的jboss-service.xml樣例:

          <?xml version="1.0"?>
          <server>
          <mbean code="org.hibernate.jmx.HibernateService"
          name="jboss.jca:service=HibernateFactory,name=HibernateFactory">
          <!-- 必須的服務(wù) -->
          <depends>jboss.jca:service=RARDeployer</depends>
          <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
          <!-- 將Hibernate服務(wù)綁定到JNDI -->
          <attribute name="JndiName">java:/hibernate/SessionFactory</attribute>
          <!-- 數(shù)據(jù)源設(shè)置 -->
          <attribute name="Datasource">java:HsqlDS</attribute>
          <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
          <!-- 事務(wù)集成 -->
          <attribute name="TransactionStrategy">
          org.hibernate.transaction.JTATransactionFactory</attribute>
          <attribute name="TransactionManagerLookupStrategy">
          org.hibernate.transaction.JBossTransactionManagerLookup</attribute>
          <attribute name="FlushBeforeCompletionEnabled">true</attribute>
          <attribute name="AutoCloseSessionEnabled">true</attribute>
          <!-- 抓取選項(xiàng) -->
          <attribute name="MaximumFetchDepth">5</attribute>
          <!-- 二級(jí)緩存 -->
          <attribute name="SecondLevelCacheEnabled">true</attribute>
          <attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>
          <attribute name="QueryCacheEnabled">true</attribute>
          <!-- 日志 -->
          <attribute name="ShowSqlEnabled">true</attribute>
          <!-- 映射定義文件 -->
          <attribute name="MapResources">auction/Item.hbm.xml,auction/Category.hbm.xml</attribute>
          </mbean>
          </server>

          這個(gè)文件是部署在META-INF目錄下的, 并會(huì)被打包到以.sar (service archive)為擴(kuò)展名的JAR文件中. 同時(shí),你需要打包Hibernate, 它所需要的第三方庫(kù), 你編譯好的持久化類及你的映射定義文件打包進(jìn)同一個(gè)文檔. 你的企業(yè)Bean(一般為會(huì)話Bean)可能會(huì)被打包成它們自己的JAR文件, 但你也許會(huì)將EJB JAR文件一同包含進(jìn)能獨(dú)立(熱)部署的主服務(wù)文檔. 咨詢JBoss AS文檔以了解更多的JMX服務(wù)與EJB部署的信息.

          posted on 2007-04-03 09:52 ???MengChuChen 閱讀(1589) 評(píng)論(0)  編輯  收藏 所屬分類: hibernate
          主站蜘蛛池模板: 山阳县| 博客| 扬中市| 大英县| 增城市| 阿鲁科尔沁旗| 婺源县| 昭平县| 共和县| 山丹县| 耿马| 芜湖市| 崇礼县| 辽源市| 新闻| 楚雄市| 龙岩市| 读书| 临汾市| 延川县| 葵青区| 沂水县| 通河县| 永清县| 平罗县| 信阳市| 安陆市| 同江市| 修武县| 墨竹工卡县| 新宾| 普陀区| 绩溪县| 湖北省| 宜良县| 都安| 台南县| 呼伦贝尔市| 神农架林区| 贵州省| 剑川县|