站内搜索: 请输入搜索关键词
当前页面: 在线文档首页 > Hibernate reference 2.1.8 ga 正式版中文参考手册

第 3 章 SessionFactory配置 - Hibernate reference 2.1.8 ga 正式版中文参考手册

第 3 章 SessionFactory配置

因为Hibernate被设计为可以在许多不同环境下工作,所以它有很多配置参数。幸运的是,大部分都已经有默认值了,Hibernate发行包中还附带有示例的hibernate.properties文件,它演示了一些可变的参数。一般你只需要把这个文件放到你的classpath,配置一下即可。

3.1. 可编程配置方式

net.sf.hibernate.cfg.Configuration的一个实例代表了应用程序中所有的Java类到SQL数据库的映射的集合。Configuration用于构造一个(不可变的)SessionFactory。这些映射是从一些XML映射文件中编译得来的。

你可以得到一个Configuration的实例,直接实例化它即可。下面有一个例子,用来从两个XML配置文件(位于classpath)中的映射中初始化:

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

另外一个(某些时候更好的)方法是让Hibernate自行用getResourceAsStream()来装载映射文件。

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

Hibernate 就会在classpath中寻找叫做/org/hibernate/autcion/Item.hbm.xml/org/hibernate/autcion/Bid.hbm.xml的映射文件。这种方法取消了所有对文件名的硬编码。

Configuration也可以指定一些可选的配置项:

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

Configuration是仅在配置期使用的对象,从第一个SessionFactory开始建立的时候,它就失效了。

3.2. 获取SessionFactory

当所有的映射都被Configuration解析之后,应用程序为了得到Session实例,必须先得到它的工厂。这个工厂应该是被应用程序的所有线程共享的:

SessionFactory sessions = cfg.buildSessionFactory();

当然,Hibernate并不禁止你的程序实例化多个SessionFactory。在你使用不止一个数据库的时候,这就有用了。

3.3. 用户自行提供JDBC连接

SessionFactory可以使用一个用户自行提供的JDBC连接来打开一个Session。这种设计可以让应用程序来自己管理JDBC连接:

java.sql.Connection conn = datasource.getConnection();
Session session = sessions.openSession(conn);

// do some data access work

应用程序必须小心,不能在同一个连接上打开两个并行的session!

3.4. Hibernate提供的JDBC连接

另一种方法就是,你可以让SessionFactory替你打开连接。SessionFactory必须事先知道JDBC连接的参数,有几种不同的方法设置参数:

  1. 传递一个java.util.PropertiesConfiguration.setProperties()方法。

  2. 在classpath的根目录中提供hibernate.properties文件。

  3. 通过java -Dproperty=value指定使用系统属性

  4. hibernate.cfg.xml文件中包含<property>元素。详情见后。

如果你使用这种方法,打开一个Session是非常简单的:

Session session = sessions.openSession(); // open a new Session
// do some data access work, a JDBC connection will be used on demand

所有的Hibernate属性名和约束都在net.sf.hibernate.cfg.Environment类中定义。我们讨论一下JDBC连接配置最重要的几项设置:

假若你设置了如下的属性,Hibernate会使用java.sql.DriverManager来得到连接,并建立连接池:

表 3.1. Hibernate JDBC属性

属性名用途
hibernate.connection.driver_classjdbc驱动类
hibernate.connection.urljdbc URL
hibernate.connection.username数据库用户名
hibernate.connection.password数据库用户密码
hibernate.connection.pool_size连接池容量最大数

Hibernate的连接池算法是非常可配置的。它的用途是让你上手,但是并非让你在生产系统中使用的,甚至不是用来做性能测试的。如果为了得到最好的性能和可靠性需要使用第三方的池,请用你连接池特定的设置来取代hibernate.connection.pool_size属性。

C3P0是随Hibernate发行包一起发布的一个开放源代码JDBC连接池,你可以在lib 目录中找到。假若你设置了hibernate.c3p0.* 属性,Hibernate会使用内置的C3P0ConnectionProvider作为连接池。 对Apache DBCP和Proxool的支持也是内置的。你必须设置hibernate.dbcp.*属性 (DBCP连接池属性)来打开DBCPConnectionProvider。如果打开hibernate.dbcp.ps.* (DBCP 语句缓存属性)可以使用Prepared statement缓存(高度推荐)。要知道它们的含义,请查阅Apache commons-pool的文档。如果你想要用Proxool,你需要设置hibernate.proxool.*系列属性。

下面是使用C3P0的一个例子:

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 = net.sf.hibernate.dialect.PostgreSQLDialect

在Application Server内使用时,Hibernate可以从JNDI中注册的javax.sql.Datasource取得连接。需要设置如下属性:

表 3.2. Hibernate 数据源(Datasource)属性

属性名用途
hibernate.connection.datasourcedatasource JNDI 名字
hibernate.jndi.urlJNDI 提供者的URL (可选)
hibernate.jndi.classJNDI InitialContextFactory的类名 (可选)
hibernate.connection.username数据库用户名 (可选)
hibernate.connection.password数据库密码 (可选)

下面是一个使用应用服务器提供的JNDI数据源的例子:

hibernate.connection.datasource = java:/comp/env/jdbc/MyDB
hibernate.transaction.factory_class = \
    net.sf.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = \
    net.sf.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = \
    net.sf.hibernate.dialect.PostgreSQLDialect

从JNDI数据源获得的JDBC连接自动具有应用服务器的容器管理事务的特性。

可以通过"hibernate.connnection"开头的属性来设置特别的连接属性。比如,你可以通过hibernate.connnection.charSet来指定charSet

通过实现net.sf.hibernate.connection.ConnectionProvider接口,你可以定义如何获得JDBC连接的策略。你可以通过设置hibernate.connection.provider_class来选择一个自定义的实现。

3.5. 可选配置属性

下面是一些在运行时可以改变Hibernate行为的其他配置。所有这些都是可选的,也有合理的默认值。

系统级别的配置只能通过java -Dproperty=value或者在hibernate.properties文件中配置,而不能通过传递给ConfigurationProperties实例来配置。

表 3.3. Hibernate配置属性

属性名用途
hibernate.dialect Hibernate方言(Dialect)的类名 - 可以让Hibernate使用某些特定的数据库平台的特性

取值. full.classname.of.Dialect

hibernate.default_schema 在生成的SQL中,scheml/tablespace的全限定名

取值. SCHEMA_NAME

hibernate.session_factory_name 自动把创建的SessionFactory以这个名字绑定到JNDI中去.

取值. jndi/composite/name

hibernate.use_outer_join 允许使用外连接抓取。已经失效。请使用max_fetch_depth

取值. true | false

hibernate.max_fetch_depth 对单根联合(一对一,多对一),设置外连接抓取树的最大深度。如果是0将关闭默认的外连接抓取。

取值. 建议设置为03之间

hibernate.jdbc.fetch_size 一个非零值,用来决定JDBC的获取量大小。(会调用Statement.setFetchSize()).
hibernate.jdbc.batch_size 一个非零值,会开启Hibernate使用JDBC2的批量更新功能

取值. 建议值在 530之间。

hibernate.jdbc.use_scrollable_resultset 允许Hibernate使用JDBC2提供的可滚动结果集。只有在使用用户自行提供的JDBC连接时,这个参数才是必需的。否则Hibernate会使用连接的元数据(metadata)。

取值. 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。默认情况下,会用connection元数据根据驱动是否支持自动判断。

取值. true|false

hibernate.cglib.use_reflection_optimizer 是否使用CGLIB来代替运行时反射操作。(系统级别属性,默认为在可能时都使用CGLIB).在调试的时候有时候使用反射会有用。

取值. true | false

hibernate.jndi.<propertyName>propertyName这个属性传递到JNDI InitialContextFactory去 (可选)
hibernate.connection.isolation 事务隔离级别 (可选).请检查java.sql.Connection来得到取值的具体意义。注意大多数数据库不会支持所有的隔离级别。

取值. 1, 2, 4, 8

hibernate.connection.<propertyName>propertyName这个JDBC 属性传递到DriverManager.getConnection()
hibernate.connection.provider_class 指定一个自定义的ConnectionProvider类名

取值. classname.of.ConnectionProvider

hibernate.cache.provider_class 指定一个自定义的CacheProvider缓存提供者的类名

取值. classname.of.CacheProvider

hibernate.cache.use_minimal_puts 优化第二级缓存操作,减少写操作,代价是读操作更频繁(对于集群缓存很有用)

取值. true|false

hibernate.cache.use_query_cache 打开查询缓存,每个查询仍然必须指明cacheable。

取值. true|false

hibernate.cache.region_prefix 用于第二级缓存区域名字的前缀

取值. prefix

hibernate.transaction.factory_class 指定一个自定义的TransactionFactory类名,Hibernate Transaction API将会使用(默认是JDBCTransactionFactory)。

取值. classname.of.TransactionFactory

jta.UserTransactionJTATransactionFactory 用来从应用服务器获取JTA UserTransaction的JNDI名

取值. jndi/composite/name

hibernate.transaction.manager_lookup_classTransactionManagerLookup的类名 - 当在JTA环境中,JVM级别的缓存被打开的时候使用.

取值. classname.of.TransactionManagerLookup

hibernate.query.substitutions 把Hibernate查询中的一些短语替换为SQL短语(比如说短语可能是函数或者字符)。

取值. hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC

hibernate.show_sql 把所有的SQL语句都输出到控制台

取值. true | false

hibernate.hbm2ddl.autoSessionFactory创建后,自动输出schema创建DDL语句到数据库.和create-drop同时使用的话,数据库schema会在SessionFactory显式关闭后被drop掉。

取值. update | create | create-drop

3.5.1. SQL Dialects SQL 方言

你总是可以为你的数据库设置一个hibernate.dialect方言,它是net.sf.hibernate.dialect.Dialect 的一个子类。如果你不需要使用基于native或者sequence的主键自动生成算法,或者悲观锁定(使用Session.lock()Query.setLockMode())的话,方言就可以不必指定。然而,假若你指定了一个方言,Hibernate会为上面列出的一些属性使用特殊默认值,省得你手工指定它们。

表 3.4. Hibernate SQL 方言 (hibernate.dialect)

RDBMS方言
DB2net.sf.hibernate.dialect.DB2Dialect
DB2 AS/400net.sf.hibernate.dialect.DB2400Dialect
DB2 OS390net.sf.hibernate.dialect.DB2390Dialect
PostgreSQLnet.sf.hibernate.dialect.PostgreSQLDialect
MySQLnet.sf.hibernate.dialect.MySQLDialect
Oracle (any version)net.sf.hibernate.dialect.OracleDialect
Oracle 9net.sf.hibernate.dialect.Oracle9Dialect
Sybasenet.sf.hibernate.dialect.SybaseDialect
Sybase Anywherenet.sf.hibernate.dialect.SybaseAnywhereDialect
Microsoft SQL Servernet.sf.hibernate.dialect.SQLServerDialect
SAP DBnet.sf.hibernate.dialect.SAPDBDialect
Informixnet.sf.hibernate.dialect.InformixDialect
HypersonicSQLnet.sf.hibernate.dialect.HSQLDialect
Ingresnet.sf.hibernate.dialect.IngresDialect
Progressnet.sf.hibernate.dialect.ProgressDialect
Mckoi SQLnet.sf.hibernate.dialect.MckoiDialect
Interbasenet.sf.hibernate.dialect.InterbaseDialect
Pointbasenet.sf.hibernate.dialect.PointbaseDialect
FrontBasenet.sf.hibernate.dialect.FrontbaseDialect
Firebirdnet.sf.hibernate.dialect.FirebirdDialect

3.5.2. 外连接抓取(Outer Join Fetching )

如果你的数据库支持ANSI或者Oracle风格的外连接,外连接抓取可能提高性能,因为可以限制和数据库交互的数量(代价是数据库自身进行了更多的工作)。外连接抓取允许你在一个select语句中就可以得到一个由多对一或者一对一连接构成的对象图。

默认情况下,抓取在叶对象,拥有代理的对象或者产生对自身的引用时终止。

对一个特定关联来说,通过在XML映射文件中设置outer-join属性可以控制是否开启抓取功能。

也可以设置hibernate.max_fetch_depth0全局关闭此功能。如果设置为1或更高的数值,对所有的一对一和多对一关联会打开外连接抓取。默认情况下,它被设置为auto,即自动外连接。但是,一对多关联和集合永远不会使用外连接抓取,除非对每个特定的关联进行明确声明。这一行为可以在运行时通过Hibernate 查询重载。

3.5.3. 二进制流

Oracle限制通过它的JDBC驱动传递的byte数组的大小。如果你希望使用很大数量的binary或者serializable 类型的话,你需要打开hibernate.jdbc.use_streams_for_binary这只能通过JVM级别设定

3.5.4. 自定义CacheProvider

通过实现net.sf.hibernate.cache.CacheProvider接口,你可以整合一个JVM级别(或者集群的)第二级缓存进来。你可以通过hibernate.cache.provider_class选择某个自定义的实现。

3.5.5. 事务策略配置

如果你希望使用Hibernate的Transaction API,你必须通过hibernate.transaction.factory_class属性指定一个Transaction实例的工厂类。 Transaction API隐藏了底层的事务机制,允许Hibernate代码在受管制和非受管制的环境下都可以运行。

内置的两个标准选择是:

net.sf.hibernate.transaction.JDBCTransactionFactory

使用数据库(JDBC)事务(默认)

net.sf.hibernate.transaction.JTATransactionFactory

使用JTA(假若已经存在一个事务,Session会在这个上下文中工作,否则会启动一个新的事务。)

你也可以自行定义你的事务策略(比如说,一个CORBA事务服务)。

如果你希望在JTA环境中为可变数据使用JVM级别的缓存,你必须指定一个获取JTA TransactionManager的策略,但这对J2EE容易来说不是标准化的:

表 3.5. JTA TransactionManagers

事务工厂类Application Server
net.sf.hibernate.transaction.JBossTransactionManagerLookupJBoss
net.sf.hibernate.transaction.WeblogicTransactionManagerLookupWeblogic
net.sf.hibernate.transaction.WebSphereTransactionManagerLookupWebSphere
net.sf.hibernate.transaction.OrionTransactionManagerLookupOrion
net.sf.hibernate.transaction.ResinTransactionManagerLookupResin
net.sf.hibernate.transaction.JOTMTransactionManagerLookupJOTM
net.sf.hibernate.transaction.JOnASTransactionManagerLookupJOnAS
net.sf.hibernate.transaction.JRun4TransactionManagerLookupJRun4
net.sf.hibernate.transaction.BESTransactionManagerLookupBorland ES

3.5.6. 绑定SessionFactory到JNDI

绑定到JNDI的Hibernate SessionFactory可以简化查找工厂和创建新Session的过程。

假若你希望把SessionFactory绑定到一个JNDI命名空间,用hibernate.session_factory_name这个属性指定一个名字(比如,java:comp/env/hibernate/SessionFactory)。如果这个属性省略了,SessionFactory不会被绑定到JNDI。(在一个只读的JNDI默认值实现的环境中,这特别有用。比如,Tomcat。)

当把SessionFactory 绑定到JNDI,Hibernate会使用hibernate.jndi.url,hibernate.jndi.class的值来获得一个初始化上下文的实例。如果他们没有指定,就会使用默认的InitialContext

如果你选择使用JNDI,EJB或者其他工具类就可以通过JNDI查询得到SessionFactory

3.5.7. 查询语言替换

你可以使用hibernate.query.substitutions定义新的Hibernate查询短语。比如说:

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

会在生成的SQL中把短语truefalse替换成整数值。

hibernate.query.substitutions toLowercase=LOWER

这可以让你重新命名SQL的LOWER函数。

3.6. Logging

通过Apache commons-logging,Hibernate记录很多事件。

commons-logging服务会直接输出到Apache log4j(如果你把log4j.jar放在你的classpath里),或者JDK1.4 logging(如果你运行JDK 1.4或以上版本)。你可以从http://jakarta.apache.org下载log4j。要使用log4j,你需要在你的classpath中放置一个log4j.properties文件。Hibernate发行包中包含一个示例的properties配置文件。

我们强烈建议你熟悉Hibernate的log信息。Hibernate的很多工作都会尽量详细的留下log,也没有让它变的难以阅读。这是用来解决问题的最基本的设施。当然也别忘了可以如前所述打开SQL 记录(hibernate.show_sql),在你要解决性能问题时,这是你第一步就需要做的。

3.7. 实现NamingStrategy(命名策略)

net.sf.hibernate.cfg.NamingStrategy接口允许你对数据库对象和schema元素指定“命名标准”。

你可以定义从Java标识符自动生成数据库标识符的规则,或者是映射文件中给出的“逻辑”字段名和表名处理为“物理”表名和字段名的规则。这个功能可以让映射文件变得简洁,消除无用的噪音(比如TBL_前缀等)。Hibernate使用的默认策略是几乎什么都不做。

你可以在增加映射(add mappings)之前调用Configuration.setNamingStrategy()来指定不同的策略。

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

net.sf.hibernate.cfg.ImprovedNamingStrategy 是一个内置的策略,对某些程序,你可以把它作为改造的起点。

3.8. XML配置文件

另一种配置属性的方法是把所有的配置都放在一个名为hibernate.cfg.xml的文件中。这个文件可以被用于替代hibernate.properties文件,如果二者都出现,它会覆盖properties文件。

XML配置文件默认会期望在CLASSPATH的根目录中找到。下面是一个例子。

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 2.0//EN"

 "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd">

<hibernate-configuration>

    <!-- a SessionFactory instance listed as /jndi/name -->
    <session-factory
        name="java:comp/env/hibernate/SessionFactory">

        <!-- properties -->
        <property name="connection.datasource">my/first/datasource</property>
        <property name="dialect">net.sf.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">false</property>
        <property name="use_outer_join">true</property>
        <property name="transaction.factory_class">
            net.sf.hibernate.transaction.JTATransactionFactory
        </property>
        <property name="jta.UserTransaction">java:comp/UserTransaction</property>

        <!-- mapping files -->
        <mapping resource="org/hibernate/auction/Item.hbm.xml"/>
        <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>

    </session-factory>

</hibernate-configuration>

配置Hibernate只需如此简单:

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

你可以使用另外一个名字的XML配置文件:

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