`
micc010
  • 浏览: 73056 次
  • 性别: Icon_minigender_1
  • 来自: 广西
社区版块
存档分类
最新评论

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

 
阅读更多
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 Data JPA中文文档[1.4.3]_springdatajpa_erlang_waitxpf_

    开发者可以通过 `EntityManager` 和 `EntityManagerFactory` 进行这些操作,但 Spring Data JPA 提供的 Repository 接口让这些操作更加简洁。 3. **Query Methods**:Spring Data JPA 支持通过方法名自动转换为 JPA...

    Struts2 Spring Jpa 配置测试

    同时,Spring需要配置JPA的`LocalContainerEntityManagerFactoryBean`,用于创建EntityManagerFactory。 4. **整合Struts2、Spring和JPA**:在Action类中,通过Spring的@Autowired注解,可以直接注入需要的Service...

    spring学习:spring data jpa

    这个框架构建在JPA(Java Persistence API)之上,提供了一种声明式的方式来操作数据库,使得开发者无需编写大量的SQL语句,而是通过注解和接口实现对数据的CRUD(创建、读取、更新、删除)操作。 首先,我们需要...

    spring整合jpa mysql

    Spring整合JPA与MySQL是现代Java企业级应用中常见的数据持久化方案,它结合了Spring框架的灵活性和Java Persistence API(JPA)的强大功能,同时利用MySQL作为关系型数据库,提供高效、便捷的数据存储和查询能力。...

    Spring和openJPA集成

    5. **使用 Spring Data Access Objects (DAO)**:Spring 提供了 `JpaRepository` 接口,可以直接用于创建数据访问层。或者,你可以自定义 DAO 类,使用 `@PersistenceContext` 注解注入 EntityManager,并使用 ...

    Struts2整合Spring、JPA

    总的来说,Struts2、Spring和JPA的整合提供了一种高效、灵活的企业级开发架构。Struts2处理Web请求,Spring管理组件和事务,JPA负责数据持久化,三者协同工作,降低了代码的耦合度,提高了开发效率和应用的可维护性...

    SpringMVC +Hibernate JPA+Spring-data-jpa实例

    3. **实体工厂(EntityManagerFactory)**:用于创建EntityManager实例,是JPA的配置中心。 4. **持久化上下文(Persistence Context)**:内存中的缓存,保存了实体的状态,提供了事务管理和懒加载等功能。 **...

    spring data jpa入门实例

    Spring Data JPA 是 Spring 框架的一个模块,它简化了数据库访问层(DAO)的开发,通过提供自动化的 Repository 实现,使得开发者无需编写大量的 CRUD(创建、读取、更新、删除)代码。Spring Data JPA 基于 Java ...

    Spring Boot+Jpa多数据源配置Demo(支持不同数据库)

    每个数据源通常会有一个对应的`JdbcTemplate`或`JpaEntityManagerFactory`。首先,我们需要在`application.yml`或`application.properties`文件中定义各自的数据库连接信息,例如: ```yaml # application.yml ...

    Spring中使用OpenJPA

    而OpenJPA则是一个持久层框架,它提供了一种方式,将Java对象与数据库中的记录进行映射,使得我们可以像操作普通Java对象一样操作数据库。 **集成步骤** 1. **添加依赖**:在你的项目中,你需要添加Spring和Open...

    Spring整合JPA

    虽然Spring Data JPA提供了很多默认的查询方法,但有时我们需要自定义更复杂的查询。这时,可以通过在Repository接口中定义`@Query`注解的方法,编写JPA的HQL(Hibernate Query Language)或SQL语句。 9. **JPA...

    SpringDataJPA学习

    1. 声明式地操作数据库:通过接口继承方式,只需要定义接口和方法签名,SpringDataJPA会自动提供实现。 2. 支持多种查询方式:包括方法名查询、@Query注解、 Specifications等。 3. 内置分页和排序支持:通过...

    Spring-JPA

    Spring-JPA通过@Autowired注入EntityManagerFactory,然后通过它创建EntityManager实例。 4. **JPA查询语言(JPQL)**: JPQL是一种面向对象的查询语言,与SQL类似但更高级,可以直接操作对象而非表。Spring-JPA允许...

    jsf+jpa+spring整合过程

    &lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&gt; &lt;bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"&gt; &lt;!-- ...

    Spring Boot使用spring-data-jpa配置Mysql多数据源

    在Spring Boot应用中,使用`spring-data-jpa`来配置MySQL多数据源是一项常见的需求,尤其是在构建大型分布式系统时,为了实现数据隔离、负载均衡或读写分离等目的。本教程将详细介绍如何在Spring Boot项目中配置多个...

    spring_jpa_demo.zip

    Spring JPA通过Repository接口提供数据访问功能,这个接口继承自JpaRepository,允许我们定义自定义的CRUD(创建、读取、更新、删除)方法。例如,我们可以创建一个UserRepository接口,定义查询用户的方法: ```...

    spring struct + jpa

    首先定义User实体,然后创建一个UserRepository接口,继承自Spring Data JPA提供的JpaRepository。在控制器中注入UserRepository,就可以直接调用其方法进行数据库操作,如查找、创建、更新和删除用户。 总结: ...

    巴巴运动网 struts2 spring jpa

    这样,当用户在购物平台上浏览商品、添加到购物车或者完成支付时,Struts2接收并处理用户的请求,调用由Spring管理的服务层方法,这些方法进一步通过JPA与数据库进行交互,完成数据的增删改查操作。 购物子文件...

    struts2+spring+jpa小例子

    Struts2、Spring 和 JPA 是Java开发中常用的三大框架,它们各自负责应用程序的不同层面:Struts2 主要处理 MVC(Model-View-Controller)架构中的控制层,Spring 提供全面的依赖注入(DI)以及面向切面编程(AOP),...

    Struts2+Spring+JPA实例

    Struts2、Spring和JPA是Java开发中常用的三大框架,它们在企业级应用开发中发挥着关键作用。Struts2作为一个成熟的MVC框架,负责处理前端请求和控制业务流程;Spring作为轻量级的IOC(Inversion of Control)和AOP...

Global site tag (gtag.js) - Google Analytics