Hibernate.org社区文档

第 2 章。设置和配置

2.1. 设置
2.2. 配置和引导
2.2.1. 软件包
2.2.2. 引导
2.3. 事件侦听器
2.4. 在 Java SE 环境中获取 EntityManager
2.5. 杂项

兼容 JPA 2.0 的 Hibernate EntityManager 建立在 Hibernate 和 Hibernate Annotations 的核心基础之上。从版本 3.5 开始,我们已将所有必需的模块捆绑在一个 Hibernate 发行版中

下载 Hibernate Core 发行版。设置类路径(在你最喜欢的 IDE 中创建新项目后)

或者,如果你使用 Maven,请添加以下依赖项


<project ...>
  ...
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate-core-version}</version>
    </dependency>
  </dependencies>
</project>

所有必需的依赖项,如 hibernate-core 和 hibernate-annotations,都将瞬态拖动过来。

我们建议你使用 Hibernate Validator 和 Bean Validation 规范功能,因为它与 Java Persistence 2 的集成已标准化。从 Hibernate 网站下载 Hibernate Validator 4 或更高版本,并在类路径中添加 hibernate-validator.jarvalidation-api.jar。或者,在 pom.xml 中添加以下依赖项。


<project>
  ...
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-validator</artifactId>
      <version>${hibernate-validator-version}</version>
    </dependency>
    ...
  </dependencies>
  ...
</project>

如果你希望使用 Hibernate Search(Hibernate 应用程序的全文搜索),请从 Hibernate 网站下载它,并在类路径中添加 hibernate-search.jar 及其依赖项。或者,在 pom.xml 中添加以下依赖项。


<project>
  ...
  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-search</artifactId>
      <version>${hibernate-search-version}</version>
    </dependency>
    ...
  </dependencies>
  ...
</project>

应用程序服务器内和独立应用程序中实体管理器的设置驻留在持久性存档中。持久性存档是一个 JAR 文件,必须定义位于 META-INF 文件夹中的 persistence.xml 文件。存档中包含的所有正确注释的类(即具有 @Entity注释),所有带注释的包和所有存档中包含的 Hibernate hbm.xml 文件将添加到持久性单元设置中,因此默认情况下,你的 persistence.xml 将非常简单


<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="sample">
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>

以下是 persistence.xml 文件更完整的一个示例


<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">
   <persistence-unit name="manager1" transaction-type="JTA">
      <provider>org.hibernate.ejb.HibernatePersistence</provider>
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <mapping-file>ormap.xml</mapping-file>
      <jar-file>MyApp.jar</jar-file>
      <class>org.acme.Employee</class>
      <class>org.acme.Person</class>
      <class>org.acme.Address</class>
      <shared-cache-mode>ENABLE_SELECTOVE</shared-cache-mode>
      <validation-mode>CALLBACK</validation-mode>
      <properties>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
         <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
      </properties>
   </persistence-unit>
</persistence>
名称

(属性)每个实体管理器必须有名称。

事务类型

(属性)使用的事务类型。JTA 或 RESOURCE_LOCAL(在 JavaEE 环境中默认 JTA,在 JavaSE 环境中默认 RESOURCE_LOCAL)。使用 jta-datasource 时,默认 JTA,如果使用 non-jta-datasource,则使用 RESOURCE_LOCAL。

提供者

提供者是 EJB 持久性提供者的完全限定类名称。如果你不使用多个 EJB3 实现,你无需定义它。当使用 EJB 持久性的多个供应商实现时需要这样做。

jta-data-source, non-jta-data-source

这是位于 javax.sql.DataSource 的 JNDI 名称。在没有 JNDI 可用数据源的情况下运行时,必须使用 Hibernate 特定属性指定 JDBC 连接(参见下文)。

映射文件

类元素指定你将映射的符合 EJB3 的 XML 映射文件。此文件必须位于类路径中。根据 EJB3 规范,Hibernate EntityManager 将尝试加载位于 jar 文件中 META_INF/orm.xml 的映射文件。当然,任何显式映射文件也将被加载。事实上,你可以在映射文件元素中提供任何 XML 文件,即 hbm 文件或 EJB3 部署描述符。

jar 文件

jar-file 元素指定要分析的 jar 文件。此 jar 文件中所有正确注释的类、带注释的包和所有 hbm.xml 文件将添加到持久性单元设置中。此元素主要用于 Java EE 环境中。在 Java SE 中使用此元素应认为是不可移植的,在这种情况下需要一个绝对 url。你也可以指向目录(这在你的测试环境中尤其有用,即 persistence.xml 文件与域模型不在同一个根目录或 jar 文件中时)。


        <jar-file>file:/home/turin/work/local/lab8/build/classes</jar-file>
排除未列出的类

不要检查主 jar 文件中的带注释的类。只有显式类将成为持久性单元的一部分。

类元素指定您将映射的完全限定类名。默认情况下,所有正确注解的类和存档中找到的所有 hbm.xml 文件都会添加到持久性单元配置中。但您可以通过类元素添加一些外部实体。作为规范的扩展,您可以在 <class> 元素中添加包名(例如 <class>org.hibernate.eg</class>)。请注意,该包将包括在包级别定义的元数据(即在 package-info.java)中,它不会包含给定包的所有类。

shared-cache-mode

默认情况下,如果用 @Cacheable 做了注解,那么实体将被选为二级缓存。但是,您可以

有关详细信息,请参阅 Hibernate Annotation 的文档。

validation-mode

默认情况下,Bean Validation(和 Hibernate Validator)将会被激活。当实体创建、更新(可选删除)时,它将在被发送到数据库之前进行验证。由 Hibernate 生成的数据库模式也体现了实体上的约束声明。

如果需要,可以对它进行微调

不幸的是,DDL 不是标准模式(尽管非常有用),您将无法将其放入 <validation-mode> 中。要使用它,请添加一个常规属性


<property name="javax.persistence.validation.mode">
  ddl
</property>

使用这种方法,您可以混合 ddl 和 callback 模式


<property name="javax.persistence.validation.mode">
  ddl, callback
</property>
properties

properties 元素用于指定供应商特定的属性。这是您定义 Hibernate 特定配置的地方。这也是您必须指定 JDBC 连接信息的地方。

以下是 JPA 2 标准属性的列表。请务必参考 Hibernate Core 文档以查看 Hibernate 的特定属性。

以下属性只能在没有任何数据源/JNDI 的 SE 环境中使用

务必在 persistence 元素中定义语法定义,因为 JPA 规范要求进行模式验证。如果 systemIdpersistence_2_0.xsd 结尾,那么 Hibernate entityManager 将使用嵌入在 hibernate-entitymanager.jar 中的版本。它不会从互联网上获取资源。


<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

JPA 规范定义了访问 EntityManagerFactoryEntityManager 的引导过程。Bootstrap 类是 javax.persistence.Persistence,例如:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("manager1");


//or
Map<String, Object> configOverrides = new HashMap<String, Object>();
configOverrides.put("hibernate.hbm2ddl.auto", "create-drop");
EntityManagerFactory programmaticEmf =
    Persistence.createEntityManagerFactory("manager1", configOverrides);

第一个版本等同于带有“空映射”的第二个版本,映射版本是将优先于在“persistence.xml”文件中定义的任何属性的一组覆盖项。在第 2.2.1 节“打包”中定义的所有属性均可传递给 createEntityManagerFactory 方法,另外还有一些其它属性:

  • javax.persistence.provider 用来定义所用的提供程序类

  • javax.persistence.transactionType 用来定义所用的事务类型(JTARESOURCE_LOCAL

  • javax.persistence.jtaDataSource 用来定义 JNDI 中的 JTA 数据源名称

  • javax.persistence.nonJtaDataSource 用来定义 JNDI 中的非 JTA 数据源名称

  • javax.persistence.lock.timeout 以毫秒为单位的悲观锁超时时间 (IntegerString)

  • javax.persistence.query.timeout 以毫秒为单位的查询超时时间 (IntegerString)

  • javax.persistence.sharedCache.mode 对应于在第 2.2.1 节“打包”中定义的 share-cache-mode 元素。

  • javax.persistence.validation.mode 对应于在第 2.2.1 节“打包”中定义的 validation-mode 元素。

调用 Persistence.createEntityManagerFactory() 时,持久性实现会使用 ClassLoader.getResource("META-INF/persistence.xml") 方法,在您的类路径中查找任何 META-INF/persistence.xml 文件。实际上,Persistence 类将查看类路径中提供的所有持久性提供程序,并逐个询问它们是否负责创建实体管理器工厂 manager1。在这些资源的列表中,每个提供程序都会尝试找到一个实体管理器,该实体管理器的名称与您在命令行中指定的名称匹配,且与在 persistence.xml 文件中指定的内容匹配(当然,提供程序 element 必须与当前的持久性提供程序匹配)。如果找不到具有正确名称的 persistence.xml,或者如果找不到预期的持久性提供程序,则会引发 PersistenceException

除了 Hibernate 系统级设置外,Hibernate 中提供的所有属性都可以设置在 persistence.xml 文件的 properties 元素中,或者作为您传递给 createEntityManagerFactory() 的映射中的覆盖项。有关完整列表,请参阅 Hibernate 参考文档。但是,EJB3 提供程序中还有几个属性可用。

表 2.1. Hibernate 实体管理器特定属性

属性名称说明
hibernate.ejb.classcache.<classname>类缓存策略 [逗号分隔的缓存区域] 的类默认无缓存,而默认区域缓存为完全限定的类名 (例如 hibernate.ejb.classcache.com.acme.Cat read-write 或 hibernate.ejb.classcache.com.acme.Cat read-write, MyRegion)。
hibernate.ejb.collectioncache.<collectionrole>类的集合缓存策略 [逗号分隔的缓存区域] 默认无缓存,而默认区域缓存为 fully.qualified.classname.role (例如 hibernate.ejb.classcache.com.acme.Cat read-write 或 hibernate.ejb.classcache.com.acme.Cat read-write, MyRegion)。
hibernate.ejb.cfgfile用于配置 Hibernate 的 XML 配置文件 (例如 /hibernate.cfg.xml)。
hibernate.archive.autodetection确定在解析 .par 文件时 Hibernate 实体管理器自动检测的元素。(默认为 class,hbm)。
hibernate.ejb.interceptor可选的 Hibernate 拦截器。拦截器实例由所有 Session 实例共享。此拦截器必须实现 org.hibernate.Interceptor 并有一个无参数构造函数。此属性不能与 hibernate.ejb.interceptor.session_scoped 结合使用。
hibernate.ejb.interceptor.session_scoped可选的 Hibernate 拦截器。拦截器实例是特定于给定 Session 实例的 (因此可以是非线程安全的)。此拦截器必须实现 org.hibernate.Interceptor 并有一个无参数构造函数。此属性不能与 hibernate.ejb.interceptor 结合使用。
hibernate.ejb.naming_strategy可选的命名策略。使用的默认命名策略是 EJB3NamingStrategy。您可能还需要考虑 DefaultComponentSafeNamingStrategy
hibernate.ejb.event.<eventtype>给定事件类型的事件侦听器列表。事件侦听器列表是逗号分隔的完全限定类名列表 (例如 hibernate.ejb.event.pre-load com.acme.SecurityListener, com.acme.AuditListener)。
hibernate.ejb.use_class_enhancer是否在部署时对应用程序服务器类进行增强 (默认为 false)。
hibernate.ejb.discard_pc_on_close如果为 true,则持久性上下文将被丢弃 (在调用方法时认为是 clear())。否则,持久性上下文将在事务完成后保持活动状态:所有对象将保持受管状态,并且任何更改都将与数据库同步 (默认为 false,即等待事务完成)。
hibernate.ejb.resource_scanner

默认情况下,Hibernate EntityManager 自行扫描带注释的类和持久性部署描述符(如 orm.xml 和 hbm.xml 文件)的资源列表。

您可以通过实现 org.hibernate.ejb.packaging.Scanner 来自定义此扫描策略。此属性由容器实现者使用,以改善与 Hibernate 的集成。

接受 Scanner 的实例或实现 Scanner 的无参数构造函数类的文件名。


请注意,您可以在同一配置中混用 XML <class> 声明和 hibernate.ejb.cfgfile 用法。请注意潜在的冲突。在 persistence.xml 中设置的属性会覆盖在已定义的 hibernate.cfg.xml 中的属性。

注意

很重要的一点是不要覆盖 hibernate.transaction.factory_class,Hibernate EntityManager 会根据 EntityManager 类型(即 JTARESOURSE_LOCAL)自动设置合适的交易工厂。如果您在 Java EE 环境中工作,那么您可能希望设置 hibernate.transaction.manager_lookup_class

以下是在 Java SE 环境中的典型配置


<persistence>
   <persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
      <class>org.hibernate.ejb.test.Cat</class>
      <class>org.hibernate.ejb.test.Distributor</class>
      <class>org.hibernate.ejb.test.Item</class>
      <properties>
         <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver"/>
         <property name="javax.persistence.jdbc.user" value="sa"/>
         <property name="javax.persistence.jdbc.password" value=""/>
         <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:."/>
         <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/
         <property name="hibernate.max_fetch_depth" value="3"/>
       
         <!-- cache configuration -->
         <property name="hibernate.ejb.classcache.org.hibernate.ejb.test.Item" value="read-write"/>
         <property name="hibernate.ejb.collectioncache.org.hibernate.ejb.test.Item.distributors" value="read-write, RegionName"/>

         <!-- alternatively to <class> and <property> declarations, you can use a regular hibernate.cfg.xml file -->
         <!-- property name="hibernate.ejb.cfgfile" value="/org/hibernate/ejb/test/hibernate.cfg.xml"/ -->
      </properties>
   </persistence-unit>
</persistence>

为了简化编程配置,Hibernate Entity Manager 提供了一个专有 API。此 API 与 Configuration API 非常类似并且共享相同概念:Ejb3Configuration。有关如何使用它的更详细的信息,请参阅 JavaDoc 和 Hibernate 参考指南。

TODO:对某些 API(如 setDatasource())进行更详细描述

Ejb3Configuration cfg = new Ejb3Configuration();

EntityManagerFactory emf = 
  cfg.addProperties( properties ) //add some properties
     .setInterceptor( myInterceptorImpl ) // set an interceptor
     .addAnnotatedClass( MyAnnotatedClass.class ) //add a class to be mapped
     .addClass( NonAnnotatedClass.class ) //add an hbm.xml file using the Hibernate convention
     .addRerousce( "mypath/MyOtherCLass.hbm.xml ) //add an hbm.xml file
     .addRerousce( "mypath/orm.xml ) //add an EJB3 deployment descriptor
     .configure("/mypath/hibernate.cfg.xml") //add a regular hibernate.cfg.xml
     .buildEntityManagerFactory(); //Create the entity manager factory

Hibernate Entity Manager 需要增强 Hibernate 核心以实现所有的 JPA 语义。它通过 Hibernate 的事件侦听器系统来实现。当您自己使用事件系统时请小心,您可能会覆盖某些 JPA 语义。一种安全的方法是将事件侦听器添加到下面给出的列表中。


请注意,如果未启用安全功能,将移除 JACC*EventListeners

您可以通过属性(请参阅 配置和启动)或通过 ejb3configuration.getEventListeners() API 来配置事件侦听器。

实体管理器工厂应被视为不可变配置持有者,定义为指向单个数据源并映射一组已定义实体。这是创建和管理 EntityManager 的入口点。 Persistence 类是用于创建实体管理器工厂的引导类。

// Use persistence.xml configuration

EntityManagerFactory emf = Persistence.createEntityManagerFactory("manager1")
EntityManager em = emf.createEntityManager(); // Retrieve an application managed entity manager
// Work with the EM
em.close();
...
emf.close(); //close at application end

实体管理器工厂通常在应用程序初始化时创建,并在应用程序结束时关闭。它的创建过程非常耗时。对于熟悉 Hibernate 的人来说,实体管理器工厂与会话工厂非常相似。实际上,实体管理器工厂是会话工厂上的一个包装器。对 entityManagerFactory 的调用是线程安全的。

借助 EntityManagerFactory,您可以检索扩展的实体管理器。扩展的实体管理器在实体管理器生存期内保持相同的持久性上下文:换句话说,实体仍在两个事务之间进行管理(除非在此期间调用 entityManager.clear())。您可以将实体管理器视为 Hibernate 会话上的一个小型包装器。

TODO 说明 emf.createEntityManager(Map)

Hibernate 实体管理器开箱即用地配置了 Hibernate 验证器。您无需自行覆盖任何事件。如果您在自己的领域模型中不使用 Hibernate 验证器注释,则不会产生性能成本。有关 Hibernate 验证器的更多信息,请参阅 Hibernate 注释参考指南。