Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to set EntityManagerFactory through constructor by @PersistenceUnit annotation

Does anyone know how to set EntityManagerFactory through constructor by @PersistenceUnit annotation. I could this through xml configuration. But i dont know the corresponding annotation configuration.

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="jpaVendorAdapter">
  <bean
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
</property>
<property name="persistenceXmlLocation" value="classpath*:META-INF/persistence.xml" />
<property name="persistenceUnitName" value="myUnit"></property>

<bean id="handler" class="com.handler.LocalHTHandler">
<constructor-arg ref="entityManagerFactory"></constructor-arg>

And it is working fine. Can we do it through annotation for my handler bean. I heard about @persistanceunit , but it can not be placed in constructor to achieve it. Is that correct?

like image 536
Tom Sebastian Avatar asked Jul 29 '13 06:07

Tom Sebastian


2 Answers

As @Dherik said you can do this via constructor. Multi data source example below (tested on SpringBoot 2.0.4):

SomeRepository.java

@Repository
public class SomeRepository {

    private final EntityManager entityManager;

    public TestService(@Qualifier("someEntityManagerFactory") EntityManager entityManager) {
        this.entityManager = entityManager;
    }
}

SomeDatabaseConfig.java

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.orm.jpa.vendor.HibernateJpaDialect;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "someEntityManagerFactory")
@EnableConfigurationProperties(JpaProperties.class)
class SomeDatabaseConfig {

    private static final String PERSISTENCE_UNIT = "some";
    private static final String[] PACKAGES_TO_SCAN = {"package.where.you.store.your.entities"};

    @Bean(name = "someDataSourceProps")
    @ConfigurationProperties("some.datasource")
    DataSourceProperties dataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean(name = "someDataSource")
    DataSource dataSource(@Qualifier("someDataSourceProps") DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
    }

    @Bean(name = "someEntityManagerFactory")
    LocalContainerEntityManagerFactoryBean entityManagerFactory(
            JpaProperties jpaProperties,
            @Qualifier("someDataSource") DataSource dataSource,
            @Qualifier("someJpaVendorAdapter") JpaVendorAdapter jpaVendorAdapter) {
        return createEntityManagerFactory(jpaProperties, dataSource, jpaVendorAdapter, PERSISTENCE_UNIT, PACKAGES_TO_SCAN);
    }

    @Bean("someJpaVendorAdapter")
    JpaVendorAdapter jpaVendorAdapter(JpaProperties jpaProperties) {
        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setShowSql(jpaProperties.isShowSql());
        return vendorAdapter;
    }

    @Bean(name = "someTransactionManager")
    PlatformTransactionManager transactionManager(@Qualifier("someEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }

    static LocalContainerEntityManagerFactoryBean createEntityManagerFactory(JpaProperties jpaProperties, DataSource dataSource, JpaVendorAdapter jpaVendorAdapter, String persistenceUnit, String[] packagesToScan) {
        final LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSource);
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setJpaDialect(new HibernateJpaDialect());
        factoryBean.setJpaPropertyMap(getVendorProperties(jpaProperties));
        factoryBean.setPersistenceUnitName(persistenceUnit);
        factoryBean.setPackagesToScan(packagesToScan);
        return factoryBean;
    }

    private static Map<String, Object> getVendorProperties(JpaProperties jpaProperties) {
        return jpaProperties.getHibernateProperties(new HibernateSettings());
    }
}

Application.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration;

@SpringBootApplication(
        exclude = {
                DataSourceAutoConfiguration.class,
                HibernateJpaAutoConfiguration.class,
                DataSourceTransactionManagerAutoConfiguration.class
        }
)
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
like image 78
luwojtaszek Avatar answered Sep 19 '22 02:09

luwojtaszek


Not possible with Spring using JSR 330 annotations. Currently it's not possible to inject EntityManagers into constructors as @PersistenceContext is defined to not be allowed on parameters. See JPA_SPEC-72 and Allow injecting EntityManagers through constructor injection (and at non-@PersistenceContext injection points in general) [SPR-10443].

like image 25
Jarek Przygódzki Avatar answered Sep 21 '22 02:09

Jarek Przygódzki