4

I want to use EntityManager in SpringBoot.

Application

@Configuration
@EnableRetry // To enable Spring retry
@EnableJpaRepositories
@EnableAspectJAutoProxy(proxyTargetClass=true)
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }    
}

MailConfig

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "mailEntityManager",
        transactionManagerRef = "mailTransactionManager",
        basePackageClasses = MmcMonitoringLog.class)

public class MailConfig {

    @Autowired(required = false)
    private PersistenceUnitManager persistenceUnitManager;

    @Bean
    @ConfigurationProperties("app.order.jpa")
    public JpaProperties orderJpaProperties() {
        return new JpaProperties();
    }

    @Bean
    @ConfigurationProperties(prefix = "app.order.datasource")
    public DataSource orderDataSource() {
        return (DataSource) DataSourceBuilder.create().type(DataSource.class).build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean orderEntityManager(
            JpaProperties orderJpaProperties) {
        EntityManagerFactoryBuilder builder = createEntityManagerFactoryBuilder(orderJpaProperties);
        return builder
                .dataSource(orderDataSource())
                .packages(MmcMonitoringLog.class)
                .persistenceUnit("ordersDs")
                .build();
    }

    @Bean
    public JpaTransactionManager orderTransactionManager(EntityManagerFactory orderEntityManager) {
        return new JpaTransactionManager(orderEntityManager);
    }

    private EntityManagerFactoryBuilder createEntityManagerFactoryBuilder(JpaProperties customerJpaProperties) {
        JpaVendorAdapter jpaVendorAdapter = createJpaVendorAdapter(customerJpaProperties);
        return new EntityManagerFactoryBuilder(jpaVendorAdapter,
                customerJpaProperties.getProperties(), this.persistenceUnitManager);
    }

    private JpaVendorAdapter createJpaVendorAdapter(JpaProperties jpaProperties) {
        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(jpaProperties.isShowSql());
        adapter.setDatabase(jpaProperties.getDatabase());
        adapter.setDatabasePlatform(jpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(jpaProperties.isGenerateDdl());
        return adapter;
    }

}

MailService

public class MailService extends TaskAdaptor implements Runnable {

    @Autowired
    MmcMonitoringLogRepository mmcMonitoringLogRepository;

    @Override
    public void run() {

   List<MmcMonitoringLog> list = mmcMonitoringLogRepository.findByMonitoringLog("1");
   ......
}

appication.properties

spring.datasource.url= jdbc:mysql://xxxx:3306/adb?autoReconnect=true&useSSL=false
spring.datasource.username=xxx
spring.datasource.password=xxx


# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect

# Hibernate ddl auto (create, create-drop, update)
spring.jpa.hibernate.ddl-auto = none

I try to implement following https://github.com/snicoll-demos/demo-multi-entity-managers/blob/master/src/main/java/demo/order/OrderConfig.java, but my SpringBoot stop straight away without throwing any exception. If I remove MailConfig, Springboot can start. What's the problem ? Am I on the right path ?

John Joe
  • 12,412
  • 16
  • 70
  • 135
  • 1
    Why are you configuring everything yourself instead of using the Spring configuration. Basically all your `spring.datasource` and `spring.jpa` properties are useless because of this. I would say work with the framework instead of around it. – M. Deinum Sep 04 '17 at 09:39
  • @M.Deinum What should i change so I can use EntityManager in mailService ? – John Joe Sep 04 '17 at 09:40
  • 1
    Delete your `MailConfig`, remove `@EnableJpaRepositories`, `@EnableAspectJAutoProxy` and `@Configuration` from your application class. All of that is already done for you by Spring Boot. – M. Deinum Sep 04 '17 at 09:43
  • @M.Deinum Done. How could i add the EM since no persistenceUnit ? – John Joe Sep 04 '17 at 09:45
  • How you normally would do it, with `@PesistenceContext`... But why would you need it you already have a repository... – M. Deinum Sep 04 '17 at 09:46
  • @M.Deinum I want to use `em.merge` – John Joe Sep 04 '17 at 09:49
  • 1
    Why? Use `repository.save`. – M. Deinum Sep 04 '17 at 09:56
  • @M.Deinum I think I understand what you mean. But can we move to chat? Just a while. – John Joe Sep 04 '17 at 09:59

3 Answers3

2

I think you have not set the values of datasource. You will need to set "app.order.jpa" and "app.order.datasource" properties in application.properties to get the example working.

About configuration properties you can read here:

http://www.baeldung.com/configuration-properties-in-spring-boot

See the example here:

https://github.com/snicoll-demos/demo-multi-entity-managers/blob/master/src/main/resources/application.properties

app.customer.datasource.url=jdbc:h2:mem:customers;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
app.customer.datasource.driver-class-name=org.h2.Driver
app.customer.jpa.properties.hibernate.hbm2ddl.auto=create

app.order.datasource.url=jdbc:h2:mem:orders;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
app.order.datasource.driver-class-name=org.h2.Driver
app.order.jpa.properties.hibernate.hbm2ddl.auto=create
Abhilekh Singh
  • 2,845
  • 2
  • 18
  • 24
2

You do not need bean configuration in spring boot, it internally manages this type of configuration. You can use the EntityManagerFactory class of JPA like

@Autowired
 EntityManagerFactory emf;
Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
1

As Mukesh Dharajiya's answer provides:

@Autowired EntityManagerFactory factory;

private manageEntities(){

    // javadoc: Create a new application-managed EntityManager. 
    // This method returns a new EntityManager instance each time it is invoked. 
    EntityManager em = emFactory.createEntityManager();

}

Edit: Actually your using LocalContainerEntityManagerFactoryBean, I just noticed, so the info below may not apply..

In your solution you trying to create a bean that would override the entityManagerFactory that springboot has already autoconfigured.

I'm not 100% sure about this, but I believe to do that you would need to either:

  1. Exclude the autoconfiguration (@EnableJpaRepositories may not work until jpa is configured):
@SpringBootApplication(exclude = {
        DataSourceAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class,
        HibernateJpaAutoConfiguration.class})
public class Application {
    public static void main(String[] args) {
        // Now spring will not autoconfigure jpa for you, so there should not already be a factory bean
        // If you do this you will need to implement all of the steps missed in the autoconfig to get jpa functioning again
        SpringApplication.run(Application.class, args);
    }
}
  1. (maybe? - did not test) Set spring.main.allow-bean-definition-overriding=true or name the bean, and autowire it using @Qualified, in properties so that you can override the existing factory bean.
Christian Meyer
  • 605
  • 8
  • 15