繁体   English   中英

LocalContainerEntityManagerFactoryBean 和 LocalEntityManagerFactoryBean 有什么区别?

[英]What is the difference between LocalContainerEntityManagerFactoryBean and LocalEntityManagerFactoryBean?

谁能解释 Spring 框架的LocalContainerEntityManagerFactoryBeanLocalEntityManagerFactoryBean之间有什么区别?

基本上JPA 规范定义了两种类型的实体管理器 他们是:

i) 应用程序管理:应用程序管理的实体管理器是指“实体管理器仅由应用程序(即我们的代码)创建和管理”。

ii) 容器管理:容器管理的实体管理器意味着“实体管理器仅由 J2EE 容器创建和管理(即我们的代码不直接管理,而是由容器创建和管理实体管理器,我们的代码通过某种方式获得 EM,例如使用 JNDI )。

注:Created and Managed(上)是指“在交易中打开、关闭和涉及实体经理”

LocalContainerEntityManagerFactoryBean - 容器管理
LocalEntityManagerFactoryBean - 应用程序管理

一个重要说明:对于基于 spring 的应用程序,差异不大 Spring 仅扮演角色(如果配置LocalContainerEntityManagerFactoryBean则作为容器,如果配置LocalEntityManagerFactoryBean则作为应用程序

文档说明了一切:

LocalContainerEntityManagerFactoryBean——来自链接:FactoryBean,它根据 JPA 的标准容器引导合同创建 JPA EntityManagerFactory。

LocalEntityManagerFactoryBean——来自链接:FactoryBean,它根据 JPA 的标准独立引导合同创建 JPA EntityManagerFactory。

本质上,唯一的区别在于他们如何创建 JPA EntityManagerFactory

LocalEntityManagerFactoryBean

是最简单也是最有限的。 您不能引用现有的 JDBC 数据源 bean 定义,并且不存在对全局事务的支持。

LocalContainerEntityManagerFactoryBean

是最强大的 JPA 设置选项,允许在应用程序中进行灵活的本地配置。 它支持指向现有 JDBC 数据源的链接,支持本地和全局事务

REF: spring-framework-reference.pdf "Spring 3"

LocalEntityManagerFactoryBean 产生一个应用程序管理的 EntityManagerFactory。

LocalContainerEntityManagerFactoryBean 生成一个容器管理的 EntityManagerFactory。

Ref: Spring 在行动 - Craig Walls

JPA 规范定义了两种实体管理器:

  • 应用程序管理——当应用程序直接从实体管理器工厂请求实体管理器时,就会创建实体管理器。 对于应用程序管理的实体管理器,应用程序负责打开或关闭实体管理器并让实体管理器参与事务。 这种类型的实体管理器最适合在不在 Java EE 容器中运行的独立应用程序中使用。

  • 容器管理——实体管理器由 Java EE 容器创建和管理。 应用程序根本不与实体管理器工厂交互。 相反,实体管理器是直接通过注入或从 JNDI 获得的。 容器负责配置实体管理器工厂。 这种类型的实体管理器最适合 Java EE 容器使用,该容器希望保持对 JPA 配置的某些控制,超出 persistence.Z0F635D0E0F3874FFF8B581C132E6CA 中指定的配置。

应用程序管理EntityManagers由调用 PersistenceProvider 的createEntityManagerFactory()方法获得的EntityManagerFactory创建。 同时,容器管理的EntityManagerFactorys是通过PersistenceProvider的createContainerEntityManagerfactory()方法获得的。

实体管理器工厂的每种风格都由相应的 Spring 工厂 bean 生产:

  • LocalEntityManagerFactoryBean产生一个应用程序管理的 EntityManagerFactory。

  • LocalContainerEntityManagerFactoryBean产生一个容器管理的 EntityManagerFactory

需要指出的是,在应用程序管理的EntityManagerFactory和容器管理的EntityManagerFactory之间做出的选择对于基于 Spring 的应用程序是完全透明的。 当您使用 Spring 和 JPA 时,处理任何一种EntityManagerFactory形式的复杂细节都被隐藏了,让您的数据访问代码专注于其真正目的:数据访问。

就 Spring 而言,应用程序管理的实体管理器工厂和容器管理的实体管理器工厂之间的唯一真正区别是如何在 Spring 应用程序上下文中配置它们。

  • LocalEntityManagerFactoryBean 和 LocalContainerEntityManagerFactoryBean 两种实现都从 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl 返回 EntityManagerFactory 引用。
  • 除非我们明确要求 Spring 使用 JTA,否则每个实现都将使用 resource_local 事务。
  • 两个实现之间的一个主要区别是 LocalContainerEntityManagerFactoryBean 提供了以编程方式设置持久性单元(数据源和 packageToScan),更灵活,因为我们可以覆盖持久性的位置。xml 文件与 LocalEntityManagerFactoryBean 相比,我们必须使用预定义的名称持久性.xml

如果两者都使用 resource_local 作为默认值,那么它不规则 LocalContainerEntityManagerFactoryBean 正在使用容器管理的事务而其他正在使用应用程序管理的事务。

在依赖注入容器外使用 JPA 时,需要由开发人员以编程方式处理事务。 如果在 Spring 依赖注入容器内使用 JPA 则它可以由 Spring 容器处理。

使用 LocalContainerEntityManagerFactoryBean 的示例

public class DataConfig {
    @Bean
    LocalContainerEntityManagerFactoryBean entityManagerFactory() {
        //LocalEntityManagerFactoryBean lfb = new LocalEntityManagerFactoryBean();
        LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
        lfb.setDataSource(dataSource());
        lfb.setPersistenceUnitName("localEntity");
        lfb.setPersistenceProviderClass(HibernatePersistence.class);
        lfb.setPackagesToScan("com.javasampleapproach.h2database.model");
        lfb.setJpaProperties(hibernateProps());
        return lfb;
    }
}
@Component
public class PostRepository {
  @Autowired
    EntityManagerFactory emf;
  }
  public void create(){
      EntityManager em = emf.createEntityManager();
      Post post = new Post("First post");
      em.getTransaction().begin();
      em.persist(post);
      em.getTransaction().commit();
  }
}

LocalEntityManagerFactoryBean 出错

java.lang.IllegalStateException:不允许在共享 EntityManager 上创建事务 - 改用 Spring 事务或 EJB CMT

public class DataConfig {
    @Bean
    LocalEntityManagerFactoryBean entityManagerFactory() {
        LocalEntityManagerFactoryBean lfb = new LocalEntityManagerFactoryBean();
        lfb.setPersistenceUnitName("localEntity");
        lfb.setPersistenceProviderClass(HibernatePersistence.class);
        lfb.setJpaProperties(hibernateProps());
        return lfb;
    }
}

@Component
    public class PostRepository {
      @Autowired
      EntityManager em;

      public void create(){
          EntityManager em = emf.createEntityManager();
          Post post = new Post("First post");
          em.getTransaction().begin();
          em.persist(post);
          em.getTransaction().commit();
      }
    }
<persistence-unit name="localEntity">
</persistence-unit>

使用 LocalEntityManagerFactoryBean 的工作代码

Spring 在 LocalEntityManagerFactoryBean 的情况下管理事务,如容器管理。

public class DataConfig {
    @Bean
    LocalEntityManagerFactoryBean entityManagerFactory() {
        LocalEntityManagerFactoryBean lfb = new LocalEntityManagerFactoryBean();
        lfb.setPersistenceUnitName("localEntity");
        lfb.setPersistenceProviderClass(HibernatePersistence.class);
        lfb.setJpaProperties(hibernateProps());
        return lfb;
    }
}

@Component
public class PostRepository {
  @Autowired
  EntityManagerFactory emf;

  @Transactional
  public void create() {
    Post post = new Post("First post");
    em.persist(post);
  }
}

<persistence-unit name="localEntity">
</persistence-unit>

这两种实现都可以在容器管理的事务下使用,如果需要更正,请更正我。

LocalEntityManagerFactoryBean 通过 PersistenceProvider.createEntityManagerFactory() 创建 EntityManagerFactory

LocalContainerEntityManagerFactoryBean 通过 PersistenceProvider.createContainterEntityManagerFactory() 创建 EntityManagerFactory

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM