`

hibernate 配置

阅读更多

由于Hibernate是为了能在各种不同环境下工作而设计的, 因此存在着大量的配置参数. 幸运的是多数配置参数都 有比较直观的默认值, 并有随Hibernate一同分发的配置样例hibernate.properties (位于etc/)来展示各种配置选项. 所需做的仅仅是将这个样例文件复制到类路径 (classpath)下做一些自定义的修改.

一个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配置属性的方式, 其他可选方式还包括:

  1. 传一个java.util.Properties实例给 Configuration.setProperties().

  2. hibernate.properties放置在类路径(classpath)的根目录下 (root directory).

  3. 通过java -Dproperty=value来设置系统 (System)属性.

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

如果想尽快体验Hbernate, hibernate.properties是最简单的方式.

Configuration实例是一个启动期间(startup-time)的对象, 一旦SessionFactory创建完成它就被丢弃了.

通常你希望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连接 :

但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处获得连接,你至少需要设置下列属性中的一个:

这里有一个使用应用程序服务器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, 你可以选择一个自定义的实现.

有大量属性能用来控制Hibernate在运行期的行为. 它们都是可选的, 并拥有适当的默认值.

警告: 其中一些属性是"系统级(system-level)的". 系统级属性可以通过java -Dproperty=valuehibernate.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意味着将关闭默认的外连接抓取.

取值 建议在03之间取值

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的批量更新.

取值 建议取530之间的值

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.<propertyName> 将JDBC属性propertyName传递到DriverManager.getConnection()中去.
hibernate.jndi.<propertyName> 将属性propertyName传递到JNDI InitialContextFactory中去.

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的日志可能地详细. 这是必要的查错利器. 最令人感兴趣的日志分类有如下这些:

在使用Hibernate开发应用程序时, 你应当总是为org.hibernate.SQL 开启debug级别的日志记录,或者开启hibernate.show_sql属性来代替它。.

另一个配置方法是在hibernate.cfg.xml文件中指定一套完整的配置. 这个文件可以当成hibernate.properties的替代。 若两个文件同时存在,它将重载前者的属性.

XML配置文件被默认是放在CLASSPATH的根目录下. 这是一个例子:

 

<?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实例 -->
<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"/>
<!-- 缓存设置 -->
<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>

如你所见, 这个方法优势在于,在配置文件中指出了映射定义文件的名字. 一旦你需要调整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();

针对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.

在你的架构中,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的引用:

为了将SessionFactory注册到JNDI中cfg.buildSessionFactory()这行代码仍需在某处被执行. 你可在一个static初始化块(像HibernateUtil中的那样)中执行它或将Hibernate部署为一个托管的服务.

为了部署在一个支持JMX的应用程序服务器上,Hibernate和 org.hibernate.jmx.HibernateService一同分发,如Jboss AS。 实际的部署和配置是由应用程序服务器提供者指定的. 这里是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">
<!-- 必须的服务 -->
<depends>jboss.jca:service=RARDeployer</depends>
<depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>
<!-- 将Hibernate服务绑定到JNDI -->
<attribute name="JndiName">java:/hibernate/SessionFactory</attribute>
<!-- 数据源设置 -->
<attribute name="Datasource">java:HsqlDS</attribute>
<attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>
<!-- 事务集成 -->
<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>
<!-- 抓取选项 -->
<attribute name="MaximumFetchDepth">5</attribute>
<!-- 二级缓存 -->
<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>

这个文件是部署在META-INF目录下的, 并会被打包到以.sar (service archive)为扩展名的JAR文件中. 同时,你需要打包Hibernate, 它所需要的第三方库, 你编译好的持久化类及你的映射定义文件打包进同一个文档. 你的企业Bean(一般为会话Bean)可能会被打包成它们自己的JAR文件, 但你也许会将EJB JAR文件一同包含进能独立(热)部署的主服务文档. 咨询JBoss AS文档以了解更多的JMX服务与EJB部署的信息.

评论

相关推荐

Global site tag (gtag.js) - Google Analytics