`

在Spring环境中建立JPA

 
阅读更多

Spring JPA 提供了三种方法创建JPA EntityManagerFactory:

LocalEntityManagerFactoryBean
LocalEntityManagerFactoryBean负责创建一个适合于仅使用JPA进行数据访问的环境的 EntityManager。 Factory bean将使用JPA PersistenceProvider 类的自动检测机制(根据JPA的 Java SE启动),而在绝大多数情况下,只需要指定persistence unit名称:

<beans>

   <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
      <property name="persistenceUnitName" value="myPersistenceUnit"/>
   </bean>

</beans>
这种JPA部署方式最为简单,但却最受限制。例如,不能连接到现有的JDBCDataSource, 并且不支持全局事务。甚至,持久化类的织入(字节码转换)也是特定于提供者的,经常需要在启动时指定一个特定的JVM代理。 总之,这种方法实际上只适用于独立的应用程序和测试环境(这正是JPA规范设计它的原因)。

仅在简单部署环境中只使用这种方式,比如独立的应用程序和集成测试。

从JNDI中获取 EntityManagerFactory
从JNDI获取 EntityManagerFactory (例如在Java EE 5环境中),仅通过修改XML配置即可实现:

<beans>

    <jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/myPersistenceUnit"/>

</beans>
在标准的Java EE 5启动过程中,Java EE服务器自动检测持久化单元(例如应用程序文件包中的META-INF/persistence.xml) ,以及Java EE部署描述符中定义给那些持久化单元命名上下文位置的环境的persistence-unit-ref项(例如web.xml)。

在这种情况下,整个持久化单元部署,包括持久化类的织入(字码码转换)都取决于Java EE服务器。 JDBC DataSource 通过在META-INF/persistence.xml 文件中的JNDI位置进行定义;EntityManager事务与服务器的JTA子系统整合。Spring仅仅用获得的EntityManagerFactory, 通过依赖注入将它传递给应用程序对象,并为它管理事务(一般通过JtaTransactionManager)。

注意,如果在同一个应用程序中使用了多个持久化单元,JNDI获取的这种持久化单元的bean名称 应该与应用程序用来引用它们的持久化单元名称相符(例如@PersistenceUnit和 @PersistenceContext注解)。

在部署到Java EE 5服务器时使用该方法。关于如何将自定义JPA提供者部署到服务器,以及允许使用服务器提供的缺省提供者之外的JPA提供者,请查看服务器文档的相关说明。

LocalContainerEntityManagerFactoryBean
LocalContainerEntityManagerFactoryBean 提供了对JPA EntityManagerFactory 的全面控制,非常适合那种需要细粒度定制的环境。LocalContainerEntityManagerFactoryBean 将基于 persistence.xml 文件创建 PersistenceUnitInfo 类,并提供 dataSourceLookup 策略和 loadTimeWeaver。 因此它可以在JNDI之外的用户定义的数据源之上工作,并控制织入流程。

<beans>
       
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="someDataSource"/>
<property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>

</beans>
这是最为强大的JPA配置方式,允许在应用程序中灵活进行本地配置。它支持连接现有JDBC DataSource , 支持本地事务和全局事务等等。然而,它也将需求强加到了运行时环境中,例如,如果持久化提供者需要字节码转换,则必须有织入ClassLoader的能力。

注意,这个选项可能与Java EE 5服务器内建的JPA功能相冲突。因此,当运行在完全Java EE 5环境中时, 要考虑从JNDI获取EntityManagerFactory。另一种可以替代的方法是,在 LocalContainerEntityManagerFactoryBean定义中通过“persistenceXmlLocation”指定相关位置, 例如“META-INF/my-persistence.xml”,并且只将包含该名称的描述符放在应用程序包文件中。因为Java EE 5服务器将只 查找默认的META-INF/persistence.xml文件,它会忽略这种定制的持久化单元,因而避免与前面Spring 驱动的JPA配置冲突。(例如,适用于Rdsin 3.1)。

在基于Spring的应用程序环境中使用该方式可获得全部JPA功能。这包括web容器,如Tomcat, 以及独立的应用程序和包含复杂持久化需求的集成测试。

何时需要加载时织入?

并非所有的JPA提供者都需要JVM代理(Hibernate就是一个例子)。 如果你的提供者不需要代理(agent)或者你有其他选择(例如通过自定义编译器或者ant任务在构建时进行增强),那么就不应该使用加载时织入。
LoadTimeWeaver 接口由Spring提供,允许JPA ClassTransformer 实例 能够根据环境(web容器/应用服务器)以特定的方式插入。 通过Java 5 代理挂钩 ClassTransformers经常是无效的 —— 代理通常在 整个虚拟机 环境下工作,并且监控 每一个 被加载的类 —— 这在生产环境下一般是不提倡的。

Spring提供了大量用于不同环境的 LoadTimeWeaver 实现类, 允许 ClassTransformer 实例能够仅用于每个classloader ,而不是每个虚拟机。

接下来将讨论在Tomcat以及使用Spring的VM代理情况下的典型JPA织入配置。

Tomcat(5.0以上)加载时的织入配置
Apache Tomcat 缺省的ClassLoader(类装载器)并不支持类的切换, 但是它允许使用用户自定义的类装载器。Spring提供了 TomcatInstrumentableClassLoader 类 (在org.springframework.instrument.classloading.tomcat 包中),这个类继承自Tomcat的类装载器 (WebappClassLoader)并且允许JPA ClassTransformer 的实例来“增强”所有由它加载的类。 简单说,JPA转化器(JPA transformer)仅仅在(使用 TomcatInstrumentableClassLoader 的)特定web应用程序中才能被使用。

为使用用户自定义的类装载器:

将 spring-tomcat-weaver.jar 复制到 $CATALINA_HOME/server/lib 下 (其中$CATALINA_HOME 表示Tomcat的安装路径)。

通过修改web application context使Tomcat使用用户自定义的类装载器(而不是默认的类装载器):

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
Tomcat 5.0.x 和 5.5.x 系列支持多个上下文路径(context locations): 服务器配置文件($CATALINA_HOME/conf/server.xml), 默认的上下文配置($CATALINA_HOME/conf/context.xml)会影响所有被部署的web应用程序、 单独部署在Server端的web应用程序的配置($CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xml) 或者与web应用程序一起(your-webapp.war/META-INF/context.xml)。从效率的角度说, 我们推荐在web-app的内部配置的方式,因为仅仅使用JPA的应用程序会使用用户自定义的类装载器。 更多具体有关可用的上下文路径的内容请参见Tomcat 5.x的文档。

注意,5.5.20之前的版本有一个XML配置解析的bug,造成 server.xml 中无法使用Loader标签,无论是否指定了classloader,也不管这个classloader是官方的还是自定义的。

        
如果你正在使用的是Tomcat 5.5.20以上的版本,就可以将useSystemClassLoaderAsParent设置成        false来解决这个问题:

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
            useSystemClassLoaderAsParent="false"/>
</Context>
将spring-tomcat-weaver.jar复制到$CATALINA_HOME/lib (where $CATALINA_HOME表示Tomcat安装根目录的位置)。

通过编辑web应用程序上下文文件,使Tomcat使用自定义的ClassLoader(而不是默认的ClassLoader):

<Context path="/myWebApp" docBase="/my/webApp/location">
    <Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
Tomcat 6.0.x (类似于5.0.x/5.5.x)系列支持几种上下文路径:(context locations): 服务器配置文件($CATALINA_HOME/conf/server.xml), 默认的上下文配置($CATALINA_HOME/conf/context.xml)会影响所有被部署的web应用程序、 单独部署在Server端的web应用程序的配置($CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xml) 或者与web应用程序一起(your-webapp.war/META-INF/context.xml)。从效率的角度说, 我们推荐在web-app的内部配置的方式,因为仅仅使用JPA的应用程序会使用用户自定义的类装载器。 更多具体有关可用的上下文路径的内容请参见Tomcat 5.x documentation。

Tomcat 5.0.x/5.5.x

Tomcat 6.0.x

所有Tomcat版本所需的最后一步,是在配置LocalContainerEntityManagerFactoryBean的时,使用 相应的LoadTimeWeaver:

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</property>
</bean>
利用这种方法,依赖工具的JPA应用程序无需代理就可以在Tomcat上运行。这在宿主应用程序依赖不同的JPA实现时尤为重要, 因为JPA转化器只适用于ClassLoader级别,它们之间是彼此隔离的。

注意
如果Tomcat使用TopLink作为JPA提供者,请将核心的toplink jar包放在$CATALINA_HOME/shared/lib文件夹中,而不再放到war中。

使用VM代理的全局加载时织入
对于需要类工具,同时现有的LoadTimeWeaver实现不提供这种支持的环境,JDK代理是唯一的解决方案。对于这种情况,Spring提供了 需要特定于Spring(但非常常用)的VM代理(spring-agent.jar)的InstrumentationLoadTimeWeaver:

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="loadTimeWeaver">
    <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
请注意在启动虚拟机时,同时启动Spring代理,方法是提供下列JVM选项:

-javaagent:/path/to/spring-agent.jar

上下文范围内的加载时织入配置
自Spring 2.5,可以使用context:load-time-weaver元素来配置 上下文范围的LoadTimeWeaver了。这种“全局”织入器由所有JPA LocalContainerEntityManagerFactoryBeans自动拣选。

这是配置加载时织入器的推荐方法,提供平台(ebLogic, OC4J, GlassFish, Tomcat, Resin, VM agent)的自动检测,以及织入器到所有织入器知道的bean的自动传播。

<context:load-time-weaver/>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    ...
</bean>

处理多持久化单元
对于那些依靠多个持久化单元位置(例如存放在classpath中的多个jar中)的应用程序, Spring提供了作为中央仓库的PersistenceUnitManager, 避免了持久化单元查找过程(的潜在开销)。缺省实现允许指定多个位置 (默认情况下classpath会搜索META-INF/persistence.xml文件),它们会被解析然后通过持久化单元名称被获取:

<bean id="pum" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<property name="persistenceXmlLocation">
    <list>
     <value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
     <value>classpath:/my/package/**/custom-persistence.xml</value>
     <value>classpath*:META-INF/persistence.xml</value>
    </list>
</property>
<property name="dataSources">
   <map>
    <entry key="localDataSource" value-ref="local-db"/>
    <entry key="remoteDataSource" value-ref="remote-db"/>
   </map>
</property>
<!-- if no datasource is specified, use this one -->
<property name="defaultDataSource" ref="remoteDataSource"/>
</bean>

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitManager" ref="pum"/>
</bean>
要注意的是,缺省实现允许在将持久化单元信息传入JPA provider之前用 PersistenceUnitPostProcessor(它允许选择持久化单元)修改它们, 传入的过程可以是通过属性声明式地传入(影响其中所有的单元)或编程式地传入。 如果没有指定persistenceUnitManager,LocalContainerEntityManagerFactoryBean 会创建一个并在内部使用它。

分享到:
评论

相关推荐

    Spring-Reference_zh_CN(Spring中文参考手册)

    12.6.1. 在Spring环境中建立JPA 12.6.1.1. LocalEntityManagerFactoryBean 12.6.1.2. LocalContainerEntityManagerFactoryBean 12.6.1.3. 处理多个持久化单元 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于...

    Spring中文帮助文档

    12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.7. 事务管理 12.8. JpaDialect III. The Web 13. Web MVC framework Web框架 13.1...

    Spring 2.0 开发参考手册

    12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.6.5. 事务管理 12.6.6. JpaDialect III. Web 13. Web框架 13.1. 介绍 13.1.1. 与...

    spring chm文档

    12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.6.5. 事务管理 12.6.6. JpaDialect III. Web 13. Web框架 13.1. 介绍 13.1.1. 与...

    Spring API

    12.6.1. 在Spring环境中建立JPA 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.7. 事务管理 12.8. JpaDialect III. The Web 13. Web MVC framework Web框架 13.1...

    spring3.0 + jpa 需要的jar包

    在Java开发中,Spring框架和Java Persistence API (JPA) 是两个非常重要的组件,用于构建高效、可维护的Web应用程序。Spring3.0是Spring框架的一个版本,它引入了许多改进和新特性,如AOP(面向切面编程)增强、支持...

    xfire spring jpa搭建环境

    "xfire spring jpa搭建环境"这个主题聚焦于如何利用XFire、Spring和JPA这三个关键组件来建立一个高效的开发环境。下面将详细介绍这三个技术以及如何将它们整合在一起。 首先,让我们理解每个组件的核心功能: 1. *...

    spring-jpa(hibernate实现)环境搭建

    在IT行业中,Spring JPA(Java Persistence API)是Spring框架的一部分,它提供了一种方便的方式来管理数据库操作。 Hibernate是JPA的一个实现,它是一个强大的对象关系映射(ORM)工具,能够将Java对象与数据库表...

    JPA环境搭建及基础映射

    在本篇中,我们将深入探讨如何搭建JPA环境以及理解其基本的映射机制。 ### **一、环境搭建** 1. **依赖引入**:首先,你需要在项目中引入JPA的依赖。如果你使用的是Maven,可以在`pom.xml`文件中添加如下的Spring ...

    JSF+Spring+JPA_Hibernate实现_的环境搭建

    这篇文档"JSF+Spring+JPA_Hibernate实现_的环境搭建.pdf"将引导你一步步建立这样的开发环境,让我们深入探讨其中涉及的知识点。 首先,**JavaServer Faces (JSF)** 是一种Java EE标准的MVC(模型-视图-控制器)框架...

    JSF+Spring+JPA(Hibernate实现)的环境搭建

    ### JSF+Spring+JPA(Hibernate实现)的环境搭建 #### 一、概述 根据提供的文件信息,本文旨在深入探讨如何构建一个基于JSF、Spring 和 JPA(使用 Hibernate 实现)的技术栈。该技术栈被视为Struts2+Spring+...

    spring和jpa

    Spring 和 JPA(Java Persistence API)是两个在 Java 开发中非常重要的技术。Spring 是一个开源的、全方位的应用程序框架,提供了依赖注入、面向切面编程、事务管理等多种功能,广泛应用于企业级应用开发。而 JPA ...

    JPA

    - **实体(Entity)**:这是JPA中代表数据库表的类。 - **实体管理器(EntityManager)**:它是JPA的核心接口,用于执行CRUD(创建、读取、更新、删除)操作。 - **持久化上下文(Persistence Context)**:它是一个...

    JPA开发所用到的所有JAR包

    在Java开发中,JPA是基于Java EE(Enterprise Edition)的Java Persistence API规范,而在Java SE(Standard Edition)环境下,我们可以使用Hibernate这样的开源实现来实现JPA的功能。Hibernate是JPA的一个流行实现...

    boot-jpa.zip

    本文将围绕"boot-jpa.zip"这个压缩包,详细阐述Spring Data JPA在实际项目中的应用,以及如何在JDK1.8环境下运行和使用。 首先,"boot-jpa.zip"是一个包含Spring Data JPA案例的jar包,这意味着它可能是一个已经...

    springboot2-jpa-demo-ccccc

    4. **实体类**:在JPA中,实体类代表数据库表。通过使用`@Entity`注解,我们可以将Java类映射到数据库表。在这个示例中,可能有两个这样的类,分别对应两张表。 5. **表映射**:使用`@Table`注解可以指定实体类所...

    ssh集成jpa和使用注解案例

    注解在JPA中的使用极大地简化了数据库模型的定义。例如,我们可以使用@Entity注解标记一个类作为实体,@Table注解指定对应的数据库表,@Id表示主键,@GeneratedValue指定主键生成策略。字段级别的注解如@Column用于...

    入门eclipse+springboot+Mysql+jpa操作CRUD实例

    JPA是Java中的对象关系映射(ORM)标准,它允许我们在Java对象和数据库表之间建立映射,从而避免了直接编写SQL语句。通过使用JPA,我们可以使用Java方法来执行CRUD操作,而不是传统的SQL语句。 首先,我们需要在...

    SpringBoot第 8 讲:SpringBoot+JPA

    在项目初始化时,可以运行这个脚本来建立测试或生产环境的数据表。 在实际应用中,我们还需要关注事务管理。SpringBoot默认使用`@Transactional`注解来管理事务,它可以在方法级别进行声明,确保数据库操作的原子性...

Global site tag (gtag.js) - Google Analytics