在J2ee應(yīng)用中,如果采用Hibernate框架,可以自動建立數(shù)據(jù)庫實(shí)體與Java實(shí)體類的映射關(guān)系,大大方便Java程序進(jìn)行持久化對象訪問和操作,從而明顯提高企業(yè)應(yīng)用開發(fā)效率,減輕Java程序與后臺數(shù)據(jù)庫的依賴性。
但是,有時候如果操作不慎,可能造成映射關(guān)系不完整(特別是存在外鍵鏈接的時候),造成訪問數(shù)據(jù)庫對象時程序有Bug。這時,可以通過參數(shù)配置,讓Hibernate在每次需要從數(shù)據(jù)庫查詢記錄或者每次插入、更新數(shù)據(jù)庫記錄時,將相應(yīng)的SQL語句輸出到控制臺,從而了解具體的數(shù)據(jù)庫操作,更好地進(jìn)行程序調(diào)試。
方法是:
1、打開hibernate.cfg.xml文件編輯界面,在Properties窗口處,點(diǎn)擊Add按鈕,選擇Show_SQL參數(shù),輸入值為True。如下圖:

2、保存hibernate.cfg.xml。
這時,再次運(yùn)行你的程序,在控制臺視圖中將會顯示相應(yīng)的SQL語句。
另外,如果按照同樣的步驟,分別加入以下參數(shù),可以讓SQL語句更加完美:
1)參數(shù):format_sql=true 使SQL語句格式更加美觀統(tǒng)一;
2)參數(shù):use_sql_comments=true 使SQL語句中自動注入注釋,增加可讀性
下圖是輸出結(jié)果的例子:

除此之外,Hibernate還有很多參數(shù),通過合理配置這些參數(shù),可以對提高Hibernate框架下對象的效率,從而實(shí)現(xiàn)對J2ee應(yīng)用的優(yōu)化。
這些參數(shù)如下:
Java,IdeaGrace,web,開發(fā),技術(shù),交流,教程 - http://www.ideagrace.com
參數(shù) | 用途 |
---|---|
hibernate.dialect | 一個Hibernate Dialect類名允許Hibernate針對特定的關(guān)系數(shù)據(jù)庫生成優(yōu)化的SQL. 取值 full.classname.of.Dialect |
hibernate.show_sql | 輸出所有SQL語句到控制臺. 有一個另外的選擇是把org.hibernate.SQL這個log category設(shè)為debug。 eg. true | false |
hibernate.format_sql | 在log和console中打印出更漂亮的SQL。 取值 true | false |
hibernate.default_schema | 在生成的SQL中, 將給定的schema/tablespace附加于非全限定名的表名上. 取值 SCHEMA_NAME |
hibernate.default_catalog | 在生成的SQL中, 將給定的catalog附加于非全限定名的表名上. 取值 CATALOG_NAME |
hibernate.session_factory_name | SessionFactory創(chuàng)建后,將自動使用這個名字綁定到JNDI中. 取值 jndi/composite/name |
hibernate.max_fetch_depth | 為單向關(guān)聯(lián)(一對一, 多對一)的外連接抓取(outer join fetch)樹設(shè)置最大深度. 值為0意味著將關(guān)閉默認(rèn)的外連接抓取. 取值 建議在0到3之間取值 |
hibernate.default_batch_fetch_size | 為Hibernate關(guān)聯(lián)的批量抓取設(shè)置默認(rèn)數(shù)量. 取值 建議的取值為4, 8, 和16 |
hibernate.default_entity_mode | 為由這個SessionFactory打開的所有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 | 如果開啟, Hibernate將收集有助于性能調(diào)節(jié)的統(tǒng)計數(shù)據(jù). 取值 true | false |
hibernate.use_identifer_rollback | 如果開啟, 在對象被刪除時生成的標(biāo)識屬性將被重設(shè)為默認(rèn)值. 取值 true | false |
hibernate.use_sql_comments | 如果開啟, Hibernate將在SQL中生成有助于調(diào)試的注釋信息, 默認(rèn)值為false. 取值 true | false |
表 3.4. Hibernate JDBC和連接(connection)屬性
屬性名 | 用途 |
---|---|
hibernate.jdbc.fetch_size | 非零值,指定JDBC抓取數(shù)量的大小 (調(diào)用Statement.setFetchSize()). |
hibernate.jdbc.batch_size | 非零值,允許Hibernate使用JDBC2的批量更新. 取值 建議取5到30之間的值 |
hibernate.jdbc.batch_versioned_data | 如果你想讓你的JDBC驅(qū)動從executeBatch()返回正確的行計數(shù) , 那么將此屬性設(shè)為true(開啟這個選項(xiàng)通常是安全的). 同時,Hibernate將為自動版本化的數(shù)據(jù)使用批量DML. 默認(rèn)值為false. eg. true | false |
hibernate.jdbc.factory_class | 選擇一個自定義的Batcher. 多數(shù)應(yīng)用程序不需要這個配置屬性. eg. classname.of.Batcher |
hibernate.jdbc.use_scrollable_resultset | 允許Hibernate使用JDBC2的可滾動結(jié)果集. 只有在使用用戶提供的JDBC連接時,這個選項(xiàng)才是必要的, 否則Hibernate會使用連接的元數(shù)據(jù). 取值 true | false |
hibernate.jdbc.use_streams_for_binary | 在JDBC讀寫binary (二進(jìn)制)或serializable (可序列化) 的類型時使用流(stream)(系統(tǒng)級屬性). 取值 true | false |
hibernate.jdbc.use_get_generated_keys | 在數(shù)據(jù)插入數(shù)據(jù)庫之后,允許使用JDBC3 PreparedStatement.getGeneratedKeys() 來獲取數(shù)據(jù)庫生成的key(鍵)。需要JDBC3+驅(qū)動和JRE1.4+, 如果你的數(shù)據(jù)庫驅(qū)動在使用Hibernate的標(biāo) 識生成器時遇到問題,請將此值設(shè)為false. 默認(rèn)情況下將使用連接的元數(shù)據(jù)來判定驅(qū)動的能力. 取值 true|false |
hibernate.connection.provider_class | 自定義ConnectionProvider的類名, 此類用來向Hibernate提供JDBC連接. 取值 classname.of.ConnectionProvider |
hibernate.connection.isolation | 設(shè)置JDBC事務(wù)隔離級別. 查看java.sql.Connection來了解各個值的具體意義, 但請注意多數(shù)數(shù)據(jù)庫都不支持所有的隔離級別. 取值 1, 2, 4, 8 |
hibernate.connection.autocommit | 允許被緩存的JDBC連接開啟自動提交(autocommit) (不建議). 取值 true | false |
hibernate.connection.release_mode | 指定Hibernate在何時釋放JDBC連接. 默認(rèn)情況下,直到Session被顯式關(guān)閉或被斷開連接時,才會釋放JDBC連接. 對于應(yīng)用程序服務(wù)器的JTA數(shù)據(jù)源, 你應(yīng)當(dāng)使用after_statement, 這樣在每次JDBC調(diào)用后,都會主動的釋放連接. 對于非JTA的連接, 使用after_transaction在每個事務(wù)結(jié)束時釋放連接是合理的. 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中去. |
表 3.5. Hibernate緩存屬性
屬性名 | 用途 |
---|---|
hibernate.cache.provider_class | 自定義的CacheProvider的類名. 取值 classname.of.CacheProvider |
hibernate.cache.use_minimal_puts | 以頻繁的讀操作為代價, 優(yōu)化二級緩存來最小化寫操作. 在Hibernate3中,這個設(shè)置對的集群緩存非常有用, 對集群緩存的實(shí)現(xiàn)而言,默認(rèn)是開啟的. 取值 true|false |
hibernate.cache.use_query_cache | 允許查詢緩存, 個別查詢?nèi)匀恍枰辉O(shè)置為可緩存的. 取值 true|false |
hibernate.cache.use_second_level_cache | 能用來完全禁止使用二級緩存. 對那些在類的映射定義中指定<cache>的類,會默認(rèn)開啟二級緩存. 取值 true|false |
hibernate.cache.query_cache_factory | 自定義實(shí)現(xiàn)QueryCache接口的類名, 默認(rèn)為內(nèi)建的StandardQueryCache. 取值 classname.of.QueryCache |
hibernate.cache.region_prefix | 二級緩存區(qū)域名的前綴. 取值 prefix |
hibernate.cache.use_structured_entries | 強(qiáng)制Hibernate以更人性化的格式將數(shù)據(jù)存入二級緩存. 取值 true|false |
表 3.6. Hibernate事務(wù)屬性
屬性名 | 用途 |
---|---|
hibernate.transaction.factory_class | 一個TransactionFactory的類名, 用于Hibernate Transaction API (默認(rèn)為JDBCTransactionFactory). 取值 classname.of.TransactionFactory |
jta.UserTransaction | 一個JNDI名字,被JTATransactionFactory用來從應(yīng)用服務(wù)器獲取JTA UserTransaction. 取值 jndi/composite/name |
hibernate.transaction.manager_lookup_class | 一個TransactionManagerLookup的類名 - 當(dāng)使用JVM級緩存,或在JTA環(huán)境中使用hilo生成器的時候需要該類. 取值 classname.of.TransactionManagerLookup |
hibernate.transaction.flush_before_completion | 如果開啟, session在事務(wù)完成后將被自動清洗(flush)。 現(xiàn)在更好的方法是使用自動session上下文管理。取值 true | false |
hibernate.transaction.auto_close_session | 如果開啟, session在事務(wù)完成后將被自動關(guān)閉。 現(xiàn)在更好的方法是使用自動session上下文管理。取值 true | false |
表 3.7. 其他屬性
屬性名 | 用途 |
---|---|
hibernate.current_session_context_class | 為"當(dāng)前" Session指定一個(自定義的)策略。eg. jta | thread | custom.Class |
hibernate.query.factory_class | 選擇HQL解析器的實(shí)現(xiàn). 取值 org.hibernate.hql.ast.ASTQueryTranslatorFactory or org.hibernate.hql.classic.ClassicQueryTranslatorFactory |
hibernate.query.substitutions | 將Hibernate查詢中的符號映射到SQL查詢中的符號 (符號可能是函數(shù)名或常量名字). 取值 hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC |
hibernate.hbm2ddl.auto | 在SessionFactory創(chuàng)建時,自動檢查數(shù)據(jù)庫結(jié)構(gòu),或者將數(shù)據(jù)庫schema的DDL導(dǎo)出到數(shù)據(jù)庫. 使用 create-drop時,在顯式關(guān)閉SessionFactory時,將drop掉數(shù)據(jù)庫schema. 取值 validate | update | create | create-drop |
hibernate.cglib.use_reflection_optimizer | 開啟CGLIB來替代運(yùn)行時反射機(jī)制(系統(tǒng)級屬性). 反射機(jī)制有時在除錯時比較有用. 注意即使關(guān)閉這個優(yōu)化, Hibernate還是需要CGLIB. 你不能在hibernate.cfg.xml中設(shè)置此屬性. 取值 true | false |
你應(yīng)當(dāng)總是為你的數(shù)據(jù)庫將hibernate.dialect屬性設(shè)置成正確的 org.hibernate.dialect.Dialect子類. 如果你指定一種方言, Hibernate將為上面列出的一些屬性使用合理的默認(rèn)值, 為你省去了手工指定它們的功夫.
表 3.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 |
表 3.9. Hibernate日志類別
類別 | 功能 |
---|---|
org.hibernate.SQL | 在所有SQL DML語句被執(zhí)行時為它們記錄日志 |
org.hibernate.type | 為所有JDBC參數(shù)記錄日志 |
org.hibernate.tool.hbm2ddl | 在所有SQL DDL語句執(zhí)行時為它們記錄日志 |
org.hibernate.pretty | 在session清洗(flush)時,為所有與其關(guān)聯(lián)的實(shí)體(最多20個)的狀態(tài)記錄日志 |
org.hibernate.cache | 為所有二級緩存的活動記錄日志 |
org.hibernate.transaction | 為事務(wù)相關(guān)的活動記錄日志 |
org.hibernate.jdbc | 為所有JDBC資源的獲取記錄日志 |
org.hibernate.hql.AST | 在解析查詢的時候,記錄HQL和SQL的AST分析日志 |
org.hibernate.secure | 為JAAS認(rèn)證請求做日志 |
org.hibernate | 為任何Hibernate相關(guān)信息做日志 (信息量較大, 但對查錯非常有幫助) |
表 3.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 |
(完)
雖然在hibernate中有show_sql選項(xiàng),但是顯示出來的語句大多類似
select * from xxx where value=?
但是有時候我們需要得到完整的SQL語句,怎么辦呢?使用P6SPY就可以完成這個任務(wù)
p6spy是一個開源軟件,它可以跟蹤任何使用jdbc的應(yīng)用產(chǎn)生的數(shù)據(jù)庫操作。特別適合于監(jiān)控ejb服務(wù)器產(chǎn)生的 sql statements。
官方網(wǎng)址:http://www.p6spy.com/
目前p6spy 適用的應(yīng)用服務(wù)器包括jboss, atg, orion, jonas, iplanet, weblogic, websphere, resin and tomcat.
下面我介紹一下p6spy在tomcat應(yīng)用程序上安裝的步驟:
(1)http://www.p6spy.com/download.html,下載zip包
(2)解壓出p6spy.jar spy.properties兩個文件
(3)將p6spy.jar 放入應(yīng)用程序的WEB-INF/lib目錄,將spy.properties放入WEB-INF/classes目錄
(4)修改spy.properties
realdriver =com.mysql.jdbc.Driver 將這行前面的#去掉
logfile = c:/spy.log 修改一個你需要的日志文件名
(5)修改hibernate.xml,修改connection.driver_class的值為com.p6spy.engine.spy.P6SpyDriver
(6)重啟tomcat
(7)這樣在c:/下的spy.log記錄了數(shù)據(jù)庫的訪問情況。
-----------------------------------------
1.下載附件的p6psy.jar以及spy.properties文件
2.將p6spy.jar放到應(yīng)用的lib目錄下,將spy.properties放到WEB-INF\classes目錄下
3.修改spy.properties樣本的第41行。改成需要的數(shù)據(jù)庫信息
修改spy.properties樣本的第54行 。改成需要的數(shù)據(jù)庫信息
修改spy.properties樣本的第168行,將spy.log放到比較好找的位置:
例如:logfile = E:/spy.log
4.驅(qū)動程序加載先后的問題解決
如果spy.log里出現(xiàn)
你的程序的數(shù)據(jù)庫驅(qū)動名稱 is a real driver in spy.properties, but it has been loaded before p6spy. p6spy will not wrap these connections. Either prevent the driver from loading, or try setting 'deregisterdrivers' to true in spy.properties
請把spy.properties文件里的deregisterdrivers=false改為deregisterdrivers=true,重新運(yùn)行即可。
5.在spring配置文件中配置如下:
- <!-- P6SPY dataSource target -->
- <bean id="dataSourceTarget" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
- <property name="driverClassName"
- value="oracle.jdbc.OracleDriver" />
- <property name="url"
- value="jdbc:oracle:thin:@localhost:1521:testdb" />
- <property name="username" value="tet" />
- <property name="password" value="test" />
- </bean>
- <!-- dataSource -->
- <bean id="dataSource4develop" class="com.p6spy.engine.spy.P6DataSource" destroy-method="close">
- <constructor-arg>
- <ref local="dataSourceTarget"/>
- </constructor-arg>
- </bean>