53

Can anybody explain what is the difference between the Spring Framework's LocalContainerEntityManagerFactoryBean and LocalEntityManagerFactoryBean?

0

7 Answers 7

47

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)

18

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.

3
  • 3
    I'm still confuse between the container and standalone. Any reference I can read?
    – huahsin68
    Commented Nov 21, 2013 at 10:03
  • 1
    @huahsin68 Maybe this answer will shead some light for you: stackoverflow.com/a/28998110/814702 Commented Nov 14, 2016 at 10:47
  • 1
    What is 'JPA's standard container bootstrap contract.' Is there any article about that? Commented Jun 12, 2022 at 23:02
18

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"

12

LocalEntityManagerFactoryBean produces an application-managed EntityManagerFactory.

LocalContainerEntityManagerFactoryBean produces a container-managed EntityManagerFactory.

Ref : Spring In Action - Craig Walls

2
  • 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.

1
  • 1st example has a spurious } after emf. 2nd injects em, but uses inexistent emf to create another inner em. 3rd injects emf, but uses inexistent em.
    – Daniel
    Commented May 5, 2021 at 9:09
1

To use JPA in a Spring project, we need to set up the EntityManager.

This is the main part of the configuration, and we can do it via a Spring factory bean. This can be either the simpler LocalEntityManagerFactoryBean or the more flexible LocalContainerEntityManagerFactoryBean.

baeldung.com/the-persistence-layer-with-spring-and-jpa

-1

LocalEntityManagerFactoryBean creates EntityManagerFactory via PersistenceProvider.createEntityManagerFactory()

LocalContainerEntityManagerFactoryBean creates EntityManagerFactory via PersistenceProvider.createContainterEntityManagerFactory()

Not the answer you're looking for? Browse other questions tagged or ask your own question.