Hibernate.org Community Documentation

- 上一页
- 下一页

## 第 3 章 配置

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

## 3.1. 可编程的配置方式

`org.hibernate.cfg.Configuration` 实例代表了一个应用程序中 Java 类型到SQL数据库映射的完整集合。`org.hibernate.cfg.Configuration` 被用来构建一个（不可变的（immutable））`org.hibernate.SessionFactory`。映射定义则由不同的 XML 映射定义文件编译而来。

你可以直接实例化 `org.hibernate.cfg.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）。

`org.hibernate.cfg.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>`（稍后讨论）。

如果你想快速上路，`hibernate.properties` 就是最容易的途径。

`org.hibernate.cfg.Configuration` 实例被设计成启动期间（startup-time）对象，一旦 `SessionFactory` 创建完成它就被丢弃了。

## 3.2. 获得 SessionFactory

当所有映射定义被 `org.hibernate.cfg.Configuration` 解析后，应用程序必须获得一个用于构造 `org.hibernate.Session` 实例的工厂。这个工厂将被应用程序的所有线程共享：

    SessionFactory sessions = cfg.buildSessionFactory();

Hibernate 允许你的应用程序创建多个 `org.hibernate.SessionFactory` 实例。这对 使用多个数据库的应用来说很有用。

## 3.3. JDBC 连接

通常你希望 `org.hibernate.SessionFactory` 来为你创建和缓存（pool）JDBC 连接。如果你采用这种方式，只需要如下例所示那样，打开一个 `org.hibernate.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 连接：

表 3.1. Hibernate JDBC 属性

属性名 | 用途
--- | ---
hibernate.connection.driver_class | JDBC driver class
hibernate.connection.url | JDBC URL
hibernate.connection.username | database user
hibernate.connection.password | 数据库用户密码
hibernate.connection.pool_size | maximum number of pooled connections

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

表 3.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`，你可以选择一个自定义的实现。

## 3.4. 可选的配置属性

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

## 警告

其中一些属性是"系统级（system-level）的"。系统级属性只能通过`java -Dproperty=value` 或 `hibernate.properties` 来设置，而不能用上面描述的其他方法来设置。

表 3.3. Hibernate 配置属性

属性名 | 用途
--- | ---
hibernate.dialect | 允许 Hibernate 针对特定的关系数据库生成优化的 SQL 的 `org.hibernate.dialect.Dialect` 的类名。 例如：`full.classname.of.Dialect` 在大多数情况下，Hibernate 可以根据 JDBC 驱动返回的 `JDBC metadata` 选择正确的 `org.hibernate.dialect.Dialect` 实现。
hibernate.show_sql | 输出所有 SQL 语句到控制台。有一个另外的选择是把 `org.hibernate.SQL` 这个 log category设为 `debug`。 例如：`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 | `org.hibernate.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_identifier_rollback | 如果开启，在对象被删除时生成的标识属性将被重设为默认值。 例如：`true` | `false`
hibernate.use_sql_comments | 如果开启，Hibernate 将在 SQL 中生成有助于调试的注释信息，默认值为 `false`。 例如：`true` | `false`
hibernate.id.new_generator_mappings | Setting is relevant when using `@GeneratedValue`. It indicates whether or not the new `IdentifierGenerator` implementations are used for `javax.persistence.GenerationType.AUTO`, `javax.persistence.GenerationType.TABLE` and `javax.persistence.GenerationType.SEQUENCE`. Default to `false` to keep backward compatibility. 例如：`true` | `false`

## 注意

We recommend all new projects which make use of to use `@GeneratedValue` to also set `hibernate.id.new_generator_mappings=true` as the new generators are more efficient and closer to the JPA 2 specification semantic. However they are not backward compatible with existing databases (if a sequence or a table is used for id generation).

表 3.4. Hibernate JDBC 和连接（connection）属性

属性名 | 用途
--- | ---
hibernate.jdbc.fetch_size | 非零值，指定 JDBC 抓取数量的大小（调用 `Statement.setFetchSize()`）。
hibernate.jdbc.batch_size | 非零值，允许 Hibernate 使用 JDBC2 的批量更新。 例如：建议取 `5` 到 `30` 之间的值
hibernate.jdbc.batch_versioned_data | Set this property to `true` if your JDBC driver returns correct row counts from `executeBatch()`. It is usually safe to turn this option on. Hibernate will then use batched DML for automatically versioned data. Defaults to `false`. 例如：`true` | `false`
hibernate.jdbc.factory_class | 选择一个自定义的 `Batcher`。多数应用程序不需要这个配置属性。 例如：`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`。 例如：`auto` (默认) | `on_close` | `after_transaction` | `after_statement` This setting only affects `Session`s returned from `SessionFactory.openSession`. For `Session`s obtained through `SessionFactory.getCurrentSession`, the `CurrentSessionContext` implementation configured for use controls the connection release mode for those `Session`s. See 第 2.3 节 “上下文相关的会话（Contextual Session）”
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` | 以频繁的读操作为代价，优化二级缓存来最小化写操作。在 Hibernate3 中，这个设置对的集群缓存非常有用，对集群缓存的实现而言，默认是开启的。 例如：`true | false`
`hibernate.cache.use_query_cache` | 允许查询缓存，个别查询仍然需要被设置为可缓存的。 例如：`true | false`
`hibernate.cache.use_second_level_cache` | 能用来完全禁止使用二级缓存。对那些在类的映射定义中指定 `<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`
`hibernate.cache.default_cache_concurrency_strategy` | Setting used to give the name of the default `org.hibernate.annotations.CacheConcurrencyStrategy` to use when either `@Cacheable` or `@Cache` is used. `@Cache(strategy="..")` is used to override this default.

表 3.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` | If enabled, the session will be automatically flushed during the before completion phase of the transaction. Built-in and automatic session context management is preferred, see 第 2.3 节 “上下文相关的会话（Contextual Session）”. 例如：`true` | `false`
`hibernate.transaction.auto_close_session` | If enabled, the session will be automatically closed during the after completion phase of the transaction. Built-in and automatic session context management is preferred, see 第 2.3 节 “上下文相关的会话（Contextual Session）”. 例如：`true` | `false`

表 3.7. 其他属性

属性名 | 用途
--- | ---
`hibernate.current_session_context_class` | Supply a custom strategy for the scoping of the "current" `Session`. See 第 2.3 节 “上下文相关的会话（Contextual Session）” for more information about the built-in strategies. 例如：`jta` | `thread` | `managed` | `custom.Class`
`hibernate.query.factory_class` | 选择 HQL 解析器的实现。 例如：`org.hibernate.hql.ast.ASTQueryTranslatorFactory` 或 `org.hibernate.hql.classic.ClassicQueryTranslatorFactory`
`hibernate.query.substitutions` | 将 Hibernate 查询中的符号映射到 SQL 查询中的符号（符号可能是函数名或常量名字）。 例如：`hqlLiteral=SQL_LITERAL, hqlFunction=SQLFUNC`
`hibernate.hbm2ddl.auto` | 在 `SessionFactory` 创建时，自动检查数据库结构，或者将数据库 schema 的 DDL 导出到数据库。使用 `create-drop` 时，在显式关闭 `SessionFactory` 时，将删除掉数据库 schema。 例如：`validate` | `update` | `create` | `create-drop`
`hibernate.hbm2ddl.import_files` | Comma-separated names of the optional files containing SQL DML statements executed during the `SessionFactory` creation. This is useful for testing or demoing: by adding INSERT statements for example you can populate your database with a minimal set of data when it is deployed. File order matters, the statements of a give file are executed before the statements of the following files. These statements are only executed if the schema is created ie if `hibernate.hbm2ddl.auto` is set to `create` or `create-drop`. e.g. `/humans.sql,/dogs.sql`
`hibernate.bytecode.use_reflection_optimizer` | Enables the use of bytecode manipulation instead of runtime reflection. This is a System-level property and cannot be set in `hibernate.cfg.xml`. Reflection can sometimes be useful when troubleshooting. Hibernate always requires either CGLIB or javassist even if you turn off the optimizer. 例如：`true` | `false`
`hibernate.bytecode.provider` | Both javassist or cglib can be used as byte manipulation engines; the default is `javassist`. e.g. `javassist` | `cglib`

### 3.4.1. SQL 方言

你应当总是为你的数据库将 `hibernate.dialect` 属性设置成正确的 `org.hibernate.dialect.Dialect` 子类。如果你指定一种方言，Hibernate 将为上面列出的一些属性使用合理的默认值，这样你就不用手工指定它们。

表 3.8. Hibernate SQL 方言（`hibernate.dialect`）

RDBMS | Dialect
--- | ---
DB2 | `org.hibernate.dialect.DB2Dialect`
DB2 AS/400 | `org.hibernate.dialect.DB2400Dialect`
DB2 OS390 | `org.hibernate.dialect.DB2390Dialect`
PostgreSQL | `org.hibernate.dialect.PostgreSQLDialect`
MySQL5 | `org.hibernate.dialect.MySQL5Dialect`
MySQL5 with InnoDB | `org.hibernate.dialect.MySQL5InnoDBDialect`
MySQL with MyISAM | `org.hibernate.dialect.MySQLMyISAMDialect`
Oracle（any version） | `org.hibernate.dialect.OracleDialect`
Oracle 9i | `org.hibernate.dialect.Oracle9iDialect`
Oracle 10g | `org.hibernate.dialect.Oracle10gDialect`
Oracle 11g | `org.hibernate.dialect.Oracle10gDialect`
Sybase | `org.hibernate.dialect.SybaseASE15Dialect`
Sybase Anywhere | `org.hibernate.dialect.SybaseAnywhereDialect`
Microsoft SQL Server 2000 | `org.hibernate.dialect.SQLServerDialect`
Microsoft SQL Server 2005 | `org.hibernate.dialect.SQLServer2005Dialect`
Microsoft SQL Server 2008 | `org.hibernate.dialect.SQLServer2008Dialect`
SAP DB | `org.hibernate.dialect.SAPDBDialect`
Informix | `org.hibernate.dialect.InformixDialect`
HypersonicSQL | `org.hibernate.dialect.HSQLDialect`
H2 Database | `org.hibernate.dialect.H2Dialect`
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.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"` 来映射。

See 第 21.1 节 “抓取策略（Fetching strategies）” for more information.

### 3.4.3. 二进制流（Binary Streams）

Oracle 限制那些通过 JDBC 驱动传输的`字节`数组的数目。如果你希望使用`二进值（binary）`或 `可序列化的（serializable）`类型的大对象，你应该开启 `hibernate.jdbc.use_streams_for_binary` 属性。这是系统级属性。

### 3.4.4. 二级缓存与查询缓存

The properties prefixed by `hibernate.cache` allow you to use a process or cluster scoped second-level cache system with Hibernate. See the 第 21.2 节 “二级缓存（The Second Level Cache）” for more information.

### 3.4.5. 查询语言中的替换

你可以使用 `hibernate.query.substitutions` 在 Hibernate 中定义新的查询符号。例如：

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

将导致符号 `true` 和 `false` 在生成的 SQL 中被翻译成整数常量。

    hibernate.query.substitutions toLowercase=LOWER

将允许你重命名 SQL 中的 `LOWER` 函数。

### 3.4.6. Hibernate 的统计（statistics）机制

如果你开启 `hibernate.generate_statistics`，那么当你通过 `SessionFactory.getStatistics()` 调整正在运行的系统时，Hibernate 将导出大量有用的数据。Hibernate 甚至能被配置成通过 JMX 导出这些统计信息。参考 `org.hibernate.stats` 中接口的 Javadoc，以获得更多信息。

## 3.5. 日志

Hibernate 利用 Simple Logging Facade for Java (SLF4J) 来记录不同系统事件的日志。SLF4J 可以根据你选择的绑定把日志输出到几个日志框架（NOP、Simple、log4j version 1.2、JDK 1.4 logging、JCL 或 logback）上。为了设置日志，你需要在 classpath 里加入 `slf4j-api.jar` 和你选择的绑定的 JAR 文件（使用 Log4J 时加入 `slf4j-log4j12.jar`）。更多的细节请参考 SLF4J 文档。要使用 Log4j，你也需要在 classpath 里加入 `log4j.properties` 文件。Hibernate 里的 `src/` 目录里带有一个属性文件的例子。

我们强烈建议你熟悉一下 Hibernate 的日志消息。在不失可读性的前提下，我们做了很多工作，使 Hibernate 的日志可能地详细。这是必要的查错利器。最令人感兴趣的日志分类有如下这些：

表 3.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.AST` | 在解析查询的时候,记录 HQL 和 SQL 的 AST 分析日志
`org.hibernate.secure` | 为 JAAS 认证请求做日志
`org.hibernate` | 为任何 Hibernate 相关信息记录日志（信息量较大，但对查错非常有帮助）

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

## 3.6. 实现 `NamingStrategy`

`org.hibernate.cfg.NamingStrategy` 接口允许你为数据库中的对象和 schema 元素指定一个“命名标准”。

你可能会提供一些通过 Java 标识生成数据库标识或将映射定义文件中"逻辑"表/列名处理成"物理"表/列名的规则。这个特性有助于减少冗长的映射定义文件，消除重复内容（如 `TBL_` 前缀）。Hibernate 使用的缺省策略是相当精简的。

在加入映射定义前，你可以调用 `Configuration.setNamingStrategy()` 指定一个不同的命名策略：

    SessionFactory sf = new Configuration()

        .setNamingStrategy(ImprovedNamingStrategy.INSTANCE)

        .addFile("Item.hbm.xml")

        .addFile("Bid.hbm.xml")

        .buildSessionFactory();

`org.hibernate.cfg.ImprovedNamingStrategy` 是一个内建的命名策略，对一些应用程序而言，可能是非常有用的起点。

## 3.7. Implementing a PersisterClassProvider

You can configure the persister implementation used to persist your entities and collections:

- by default, Hibernate uses persisters that make sense in a relational model and follow Java Persistence's specification

- you can define a `PersisterClassProvider` implementation that provides the persister class used of a given entity or collection

- finally, you can override them on a per entity and collection basis in the mapping using `@Persister` or its XML equivalent

The latter in the list the higher in priority.

You can pass the `PersisterClassProvider` instance to the `Configuration` object.

    SessionFactory sf = new Configuration()

        .setPersisterClassProvider(customPersisterClassProvider)

        .addAnnotatedClass(Order.class)

        .buildSessionFactory();

The persister class provider methods, when returning a non null persister class, override the default Hibernate persisters. The entity name or the collection role are passed to the methods. It is a nice way to centralize the overriding logic of the persisters instead of spreading them on each entity or collection mapping.

## 3.8. XML 配置文件

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

XML 配置文件被默认是放在 `CLASSPATH` 的根目录下。下面是一个例子：

    <?xml version='1.0' encoding='utf-8'?>

    <!DOCTYPE hibernate-configuration PUBLIC

        "-//Hibernate/Hibernate Configuration DTD//EN"

        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

    <hibernate-configuration>

        <!-- a SessionFactory instance listed as /jndi/name -->

        <session-factory

            name="java:hibernate/SessionFactory">

            <!-- properties -->

            <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 files -->

            <mapping resource="org/hibernate/auction/Item.hbm.xml"/>

            <mapping resource="org/hibernate/auction/Bid.hbm.xml"/>

            <!-- cache settings -->

            <class-cache class="org.hibernate.auction.Item" usage="read-write"/>

            <class-cache class="org.hibernate.auction.Bid" usage="read-only"/>

            <collection-cache collection="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();

## 3.9. Java EE Application Server integration

针对 J2EE 体系，Hibernate 有如下几个集成的方面：

- 容器管理的数据源（Container-managed datasources）： Hibernate 能使用通过容器管理，并由 JNDI 提供的 JDBC 连接。通常，特别是当处理多个数据源的分布式事务的时候，由一个 JTA 兼容的 `TransactionManager` 和一个 `ResourceManager` 来处理事务管理（CMT，容器管理的事务）。当然你可以通过 编程方式来划分事务边界（BMT，Bean 管理的事务）。或者为了代码的可移植性，你也也许会想使用可选的 Hibernate `Transaction` API。

- 自动 JNDI 绑定：Hibernate 可以在启动后将 `SessionFactory` 绑定到 JNDI。

- JTA Session 绑定： Hibernate `Session` 可以自动绑定到 JTA 事务作用的范围。只需简单地从 JNDI 查找 `SessionFactory` 并获得当前的 `Session`。当 JTA 事务完成时，让 Hibernate来处理 `Session` 的清洗（flush）与关闭。事务的划分可以是声明式的（CMT）,也可以是编程式的（BMT/UserTransaction）。

- JMX 部署： 如果你使用支持 JMX 应用程序服务器（如，JBoss AS），那么你可以选择将 Hibernate 部署成托管 MBean。这将为你省去一行从`Configuration` 构建 `SessionFactory` 的启动代码。容器将启动你的 `HibernateService`，并完美地处理好服务间的依赖关系（在 Hibernate 启动前，数据源必须是可用的，等等）。

如果应用程序服务器抛出 "connection containment" 异常，根据你的环境，也许该将配置属性 `hibernate.connection.release_mode` 设为 `after_statement`。

### 3.9.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 的一些特性（比如二级缓存，Contextual Sessions with JTA 等等）需要访问在托管环境中的 JTA `TransactionManager`。由于 J2EE 没有标准化一个单一的机制，Hibernate 在应用程序服务器中，你必须指定 Hibernate 如何获得 `TransactionManager` 的引用：

表 3.10. JTA TransactionManagers

Transaction 工厂类 | 应用程序服务器
--- | ---
`org.hibernate.transaction.JBossTransactionManagerLookup` | JBoss AS
`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
`org.hibernate.transaction.JBossTSStandaloneTransactionManagerLookup` | JBoss TS used standalone (ie. outside JBoss AS and a JNDI environment generally). Known to work for `org.jboss.jbossts:jbossjta:4.11.0.Final`

### 3.9.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`。

It is recommended that you bind the `SessionFactory` to JNDI in a managed environment and use a `static` singleton otherwise. To shield your application code from these details, we also recommend to hide the actual lookup code for a `SessionFactory` in a helper class, such as `HibernateUtil.getSessionFactory()`. Note that such a class is also a convenient way to startup Hibernate—see chapter 1.

### 3.9.3. 在 JTA 环境下使用 Current Session context（当前 session 上下文）管理

The easiest way to handle `Sessions` and transactions is Hibernate's automatic "current" `Session` management. For a discussion of contextual sessions see 第 2.3 节 “上下文相关的会话（Contextual Session）”. Using the `"jta"` session context, if there is no Hibernate `Session` associated with the current JTA transaction, one will be started and associated with that JTA transaction the first time you call `sessionFactory.getCurrentSession()`. The `Session`s retrieved via `getCurrentSession()` in the `"jta"` context are set to automatically flush before the transaction completes, close after the transaction completes, and aggressively release JDBC connections after each statement. This allows the `Session`s to be managed by the life cycle of the JTA transaction to which it is associated, keeping user code clean of such management concerns. Your code can either use JTA programmatically through `UserTransaction`, or (recommended for portable code) use the Hibernate `Transaction` API to set transaction boundaries. If you run in an EJB container, declarative transaction demarcation with CMT is preferred.

### 3.9.4. JMX 部署

为了将 `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">

        <!-- Required services -->

        <depends>jboss.jca:service=RARDeployer</depends>

        <depends>jboss.jca:service=LocalTxCM,name=HsqlDS</depends>

        <!-- Bind the Hibernate service to JNDI -->

        <attribute name="JndiName">java:/hibernate/SessionFactory</attribute>

        <!-- Datasource settings -->

        <attribute name="Datasource">java:HsqlDS</attribute>

        <attribute name="Dialect">org.hibernate.dialect.HSQLDialect</attribute>

        <!-- Transaction integration -->

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

        <!-- Fetching options -->

        <attribute name="MaximumFetchDepth">5</attribute>

        <!-- Second-level caching -->

        <attribute name="SecondLevelCacheEnabled">true</attribute>

        <attribute name="CacheProviderClass">org.hibernate.cache.EhCacheProvider</attribute>

        <attribute name="QueryCacheEnabled">true</attribute>

        <!-- Logging -->

        <attribute name="ShowSqlEnabled">true</attribute>

        <!-- Mapping files -->

        <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 部署的信息。

版权 © 2004 Red Hat, Inc.

- 上一页第 2 章 体系结构（Architecture）
- 上一级
- 起始页
- 下一页第 4 章 持久化类（Persistent Classes）