Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I lazy create the EntityManagerFactory using Spring Data ORM/JPA?

I'm creating a standalone Java application that uses Spring Data with JPA.

Part of the class that creates the factory for the EntityManagerFactory is below:

@Configuration
@Lazy
public class JpaConfig {

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(MultiTenantConnectionProvider connProvider,  CurrentTenantIdentifierResolver tenantResolver) {
...
}

The problem is: I can only detect the Hibernate Dialect after the ApplicationContext is initialized, because this information is read from an external configuration service.

Since @Lazy did not work, is there any strategy to avoid creating this bean before it is used, i.e, only create it when another bean injects an instance of EntityManager?

like image 553
Toresan Avatar asked Feb 01 '26 19:02

Toresan


1 Answers

I stumbled upon this issue recently and found a solution that worked. Unfortunately "container" managed beans will be initialized during startup and @Lazy is ignored even if the EntityManager is not injected anywhere.

I fixed it by using an in-memory H2 DB to construct the factory bean during startup and changed it later. I think here's what you can do for your issue.

pom.xml:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.199</version>
</dependency>

Source code:

@Configuration
public class DataSourceConfig {

    @Bean
    public HikariDataSource realDataSource() {
        ...
    }

    @Bean
    public DataSource localH2DataSource() {
        return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean myEntityManagerFactory() throws PropertyVetoException {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        
        factoryBean.setDataSource(localH2DataSource());

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setShowSql(true);
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);

        return factoryBean;
    }
}

@Component
@Lazy
public class Main {

    @Autowired
    private LocalContainerEntityManagerFactoryBean emf;

    @Autowired
    private HikariDataSource realDataSource;

    @PostConstruct
    private void updateHibernateDialect() {
        // read the external config here
        emf.setDataSource(realDataSource);
        
        Properties jpaProperties = new Properties();
        jpaProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.DB2Dialect");
        factoryBean.setJpaProperties(jpaProperties);
    }
}
like image 158
Hari Samala Avatar answered Feb 04 '26 08:02

Hari Samala



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!