【发布时间】:2011-09-03 15:37:31
【问题描述】:
谁能解释一下 Spring Framework 的 LocalContainerEntityManagerFactoryBean 和 LocalEntityManagerFactoryBean 有什么区别?
【问题讨论】:
标签: spring hibernate jpa entitymanager spring-orm
谁能解释一下 Spring Framework 的 LocalContainerEntityManagerFactoryBean 和 LocalEntityManagerFactoryBean 有什么区别?
【问题讨论】:
标签: spring hibernate jpa entitymanager spring-orm
文档说明了一切:
LocalContainerEntityManagerFactoryBean -- 来自链接:FactoryBean,它根据 JPA 的标准 container 引导合同创建 JPA EntityManagerFactory。
LocalEntityManagerFactoryBean -- 来自链接:FactoryBean,它根据 JPA 的标准 standalone 引导合同创建 JPA EntityManagerFactory。
本质上,唯一的区别在于它们如何创建 JPA EntityManagerFactory。
【讨论】:
LocalEntityManagerFactoryBean
是最简单也是最有限的。您不能引用现有的 JDBC DataSource bean 定义且不支持全局事务。
LocalContainerEntityManagerFactoryBean
是最强大的 JPA 设置 选项,允许在应用程序中进行灵活的本地配置。它支持到现有 JDBC 数据源的链接,同时支持本地和全局事务
参考:spring-framework-reference.pdf "Spring 3"
【讨论】:
LocalEntityManagerFactoryBean 产生一个应用程序管理的 EntityManagerFactory。
LocalContainerEntityManagerFactoryBean 产生一个容器管理的 EntityManagerFactory。
Ref : Spring In Action - Craig Walls
【讨论】:
基本上JPA 规范 定义了两种类型的实体管理器。它们是:
i) 应用程序管理: 应用程序管理实体管理器是指“实体管理器仅由应用程序(即我们的代码)创建和管理”。
ii) 容器管理: 容器管理的实体管理器意味着“实体管理器仅由 J2EE 容器创建和管理(即我们的代码不直接管理,而是由容器创建和管理实体管理器) ,并且我们的代码通过某种方式(例如使用 JNDI)获取 EM。
注意:Created and Managed(上)表示“在交易中打开、关闭和涉及实体管理器”
LocalContainerEntityManagerFactoryBean - 容器管理
LocalEntityManagerFactoryBean - 应用程序管理
重要提示:对于基于 Spring 的应用程序,差别不大。 Spring 仅扮演角色(如果您配置 LocalContainerEntityManagerFactoryBean,则作为 容器,如果您配置 LocalEntityManagerFactoryBean应用程序 /em>)
【讨论】:
JPA 规范定义了两个 实体管理器的种类:
应用程序管理——实体管理器是在应用程序直接创建时创建的 从实体管理器工厂请求一个。使用应用程序管理的实体 manager,应用程序负责打开或关闭实体管理器 并让实体经理参与交易。这种类型的实体管理器是 最适合在不在 Java EE 中运行的独立应用程序中使用 容器。
容器管理——实体管理器由 Java EE 创建和管理 容器。应用程序不与实体管理器工厂交互 全部。相反,实体管理器是直接通过注入或从 JNDI。容器负责配置实体管理器工厂。 这种类型的实体管理器最适合 Java EE 容器使用 想要保持对 JPA 配置的一些控制,超出 persistence.xml 中指定的内容。
应用程序管理 EntityManagers 由调用 PersistenceProvider 的 createEntityManagerFactory() 方法获得的 EntityManagerFactory 创建。同时,container-managedEntityManagerFactorys是通过PersistenceProvider的createContainerEntityManagerfactory()方法获取的。
实体管理器工厂的每一种风格都由相应的 Spring 工厂 bean 产生:
LocalEntityManagerFactoryBean 生成应用程序管理的实体-
经理工厂。
LocalContainerEntityManagerFactoryBean 生成容器管理的
EntityManagerFactory
重要的是要指出,在应用程序管理之间做出的选择
EntityManagerFactory 和容器管理的 EntityManagerFactory 对基于 Spring 的应用程序是完全透明的。当您使用 Spring 和 JPA 时,处理EntityManagerFactory 的任何一种形式的复杂细节都被隐藏了,让您的数据访问代码专注于其真正目的:数据访问。
就 Spring 而言,application-managed 和 container-managed 实体管理器工厂之间的唯一真正区别在于它们在 Spring 应用程序上下文中的配置方式.
【讨论】:
LocalEntityManagerFactoryBean 通过 PersistenceProvider.createEntityManagerFactory() 创建 EntityManagerFactory
LocalContainerEntityManagerFactoryBean 通过 PersistenceProvider.createContainterEntityManagerFactory() 创建 EntityManagerFactory
【讨论】:
如果两者都使用 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 的工作代码
在 LocalEntityManagerFactoryBean 的情况下,类似容器管理的 Spring 托管事务。
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>
这两种实现都可以在容器管理事务下使用,如果需要更正,请纠正我。
【讨论】:
要在 Spring 项目中使用 JPA,我们需要设置 EntityManager。
这是配置的主要部分,我们可以通过 Spring 工厂 bean 来完成。 这可以是更简单的 LocalEntityManagerFactoryBean 或更灵活的 LocalContainerEntityManagerFactoryBean。
baeldung.com/the-persistence-layer-with-spring-and-jpa
【讨论】: