Can anybody explain what is the difference between the Spring Framework's LocalContainerEntityManagerFactoryBean and LocalEntityManagerFactoryBean?
Basically JPA specification defines two types of entity managers. They are :
i) Application-Managed : Application Managed entity manager means "Entity Managers are created and managed by merely the application ( i.e. our code )" .
ii) Container Managed : Container Managed entity manager means "Entity Managers are created and managed by merely the J2EE container ( i.e. our code doesn't directly manages instead entity managers are created and managed by container , and our code gets EM's through some way like using JNDI ).
Note : Created and Managed (above) means "opening , closing and involving entity manager in transactions"
LocalContainerEntityManagerFactoryBean - container managed
LocalEntityManagerFactoryBean - application managed
A Big Note : For spring based applications, the difference is not much. Spring only plays roles ( as container if you configure LocalContainerEntityManagerFactoryBean and as application if you configure LocalEntityManagerFactoryBean)
The documentation says it all:
LocalContainerEntityManagerFactoryBean -- From the link: FactoryBean that creates a JPA EntityManagerFactory according to JPA's standard container bootstrap contract.
LocalEntityManagerFactoryBean -- From the link: FactoryBean that creates a JPA EntityManagerFactory according to JPA's standard standalone bootstrap contract.
Essentially, the only difference is in how they create the JPA EntityManagerFactory
.
LocalEntityManagerFactoryBean
is the simplest and the most limited. You cannot refer to an existing JDBC DataSource bean definition and no support for global transactions exists.
LocalContainerEntityManagerFactoryBean
is the most powerful JPA setup option, allowing for flexible local configuration within the application. It supports links to an existing JDBC DataSource, supports both local and global transactions
REF: spring-framework-reference.pdf "Spring 3"
LocalEntityManagerFactoryBean produces an application-managed EntityManagerFactory.
LocalContainerEntityManagerFactoryBean produces a container-managed EntityManagerFactory.
Ref : Spring In Action - Craig Walls
The JPA specification defines two kinds of entity managers:
Application-managed—Entity managers are created when an application directly requests one from an entity manager factory. With application-managed entity managers, the application is responsible for opening or closing entity managers and involving the entity manager in transactions. This type of entity manager is most appropriate for use in standalone applications that don’t run in a Java EE container.
Container-managed—Entity managers are created and managed by a Java EE container. The application doesn’t interact with the entity manager factory at all. Instead, entity managers are obtained directly through injection or from JNDI. The container is responsible for configuring the entity manager factories. This type of entity manager is most appropriate for use by a Java EE container that wants to maintain some control over JPA configuration beyond what’s specified in persistence.xml.
Application-managed EntityManagers
are created by an EntityManagerFactory
obtained by calling the createEntityManagerFactory()
method of the PersistenceProvider. Meanwhile, container-managed EntityManagerFactorys are obtained through PersistenceProvider’s createContainerEntityManagerfactory()
method.
Each flavor of entity manager factory is produced by a corresponding Spring factory bean:
LocalEntityManagerFactoryBean
produces an application-managed Entity- ManagerFactory.LocalContainerEntityManagerFactoryBean
produces a container-managed EntityManagerFactory
It’s important to point out that the choice made between an application-managed
EntityManagerFactory
and a container-managed EntityManagerFactory
is completely transparent to a Spring-based application. When you’re working with Spring and JPA, the intricate details of dealing with either form of EntityManagerFactory
are hidden, leaving your data-access code to focus on its true purpose: data access.
The only real difference between application-managed and container-managed entity manager factories, as far as Spring is concerned, is how each is configured in the Spring application context.
- Both implementations LocalEntityManagerFactoryBean and LocalContainerEntityManagerFactoryBean returns EntityManagerFactory reference from org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.
- Each implementation will use resource_local transaction unless we explicitly ask Spring to use JTA.
- A major difference between the two implementations is LocalContainerEntityManagerFactoryBean provide programmatically setting persistence unit (data source & packageToScan), is more flexible in that we can override the location of the persistence.xml file compare to LocalEntityManagerFactoryBean in which we have to use a predefined name persistence.xml
If both are using resource_local as default then it does not thumb rule that LocalContainerEntityManagerFactoryBean is using container-managed transaction and other is using application-managed transaction.
When using JPA outside of a dependency injection container, transactions need to be handled programmatically by the developer. If using JPA inside of Spring dependency injection container then it can be handled by Spring container.
Example using 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();
}
}
Error with LocalEntityManagerFactoryBean
java.lang.IllegalStateException: Not allowed to create a transaction on shared EntityManager - use Spring transactions or EJB CMT instead
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>
Working code with LocalEntityManagerFactoryBean
Spring managed transaction like container-managed in case of 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>
Both implementations can be used under container-managed transaction, please correct me on this if some correction is need.
LocalEntityManagerFactoryBean creates EntityManagerFactory via PersistenceProvider.createEntityManagerFactory()
LocalContainerEntityManagerFactoryBean creates EntityManagerFactory via PersistenceProvider.createContainterEntityManagerFactory()
来源:https://stackoverflow.com/questions/6156832/what-is-the-difference-between-localcontainerentitymanagerfactorybean-and-locale