28

In a Spring Boot application I'm trying to setup multiple database connections. I've started building the primary datasource, but I'm getting the following error on the mySqlEntityManagerFactory method.

Could not autowire. no beans of EntityManagerFactoryBuilder

import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@Transactional
@EnableTransactionManagement
@EnableJpaRepositories(
        basePackages = "digital.sheppard.dao",
        entityManagerFactoryRef = "entityManager",
        transactionManagerRef = "transactionManager")
public class PrimaryDBConfig {

    @Bean(name="dataSource")
    @Primary
    @ConfigurationProperties(prefix = "primary.datasource.mysql")
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @PersistenceContext(unitName = "primary")
    @Primary
    @Bean(name = "entityManager")
    public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(mysqlDataSource()).persistenceUnit("primary").properties(jpaProperties())
                .packages("digital.sheppard.model").build();
    }

    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<String, Object>();
        props.put("hibernte.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
        props.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");

        return props;
    }

}

How would I autowire the EntityManagerFactoryBuilder?

I'm trying to follow the code on this blog https://raymondhlee.wordpress.com/2015/10/31/configuring-multiple-jpa-entity-managers-in-spring-boot/

Here's the main application class if it's helpful

@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@ComponentScan
public class Application extends SpringBootServletInitializer {

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

}
SheppardDigital
  • 3,165
  • 8
  • 44
  • 74

9 Answers9

7

For me the reason was a wrong import, so I advise everybody to look at the often overlooked import section of your configuration class. There is a Hibernate class named the same as the springframework one. Of course you should choose the spring one...

  • Worked for me. My IDE made it too easy for me to choose the Hibernate package for `EntityManagerFactoryBuilder` instead of the correct. Make sure you have: `import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;` – Eric Kramer Jan 24 '23 at 23:58
  • I was tearing my hair out trying to find what went wrong for a couple hours but this did the trick you're a lifesaver – Adam Lee Aug 25 '23 at 07:17
2

I think you should remove this code

@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
Y.Ido
  • 333
  • 1
  • 11
2

The exception is due to public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory(EntityManagerFactoryBuilder builder) { which expects a bean of EntityManagerFactoryBuilder.

I checked the reference link, I am not sure if that code will work.

Typically, one creates an instance of LocalContainerEntityManagerFactoryBean and initializes it as per need. In your case you can do

  LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
  em.setDataSource(mysqlDataSource());
  em.setPersistenceUnitName("primary");
  em.setPackagesToScan(new String[] { "digital.sheppard.model" });

  JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
  em.setJpaVendorAdapter(vendorAdapter);
  em.setJpaProperties(jpaProperties());

The persistence unit name should be same as defined in persistence.xml, though the file is now optional when using Spring JPA.

For a non spring version check out https://stackoverflow.com/a/26814642/776548

Also

  • since you are initializing EntityManagerFactory by yourself, we will have to exclude DataSourceAutoConfiguration.class.
  • @Primary is only required if you want multiple datasources. If you have only one, consider removing the annotation, and add it when you need to have multiple data sources
Archit
  • 913
  • 1
  • 10
  • 20
1

Change parameter name builder to entityManagerFactoryBuilder to inject bean present in JpaBaseConfiguration.class

Lukas
  • 812
  • 1
  • 14
  • 43
  • 3
    Does not work for me. Addin @Primary to one of the two configurations fixed this bug for me. Although I've read that Primary should not be necessary. – isgoed Aug 24 '20 at 14:49
  • 1
    Same here, adding `@Primary` fixed it. Which doesn't seem right. I'll see if I can narrow it down into a small reproducible project and report it to the Spring project as a bug. – Frans Sep 29 '20 at 15:09
0

Have you tried to remove your exclusion of 'DataSourceAutoConfiguration' ?

Using '@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})' prevent a lot of beans from beeing created.

If you got a problem when using a datasource and adding this is your solution, maybe it's not the right one.

Know that spring boot detect the presence of certain classes in the classpath. If you're using maven, it's reading all classes from all dependencies.

So consider let this DataSourceAutoConfiguration.class running;

cheers

Mathan
  • 7
  • 5
0

It could be, notice that just could be, your main class is not at the top of the "class tree". Spring needs to scan all classes that are a child (according to package convention) starting from the main class.

Maybe you would read https://www.baeldung.com/spring-component-scanning

If your classes aren't been read by spring scan, they will never be into spring context.

cehdmoy
  • 46
  • 5
0

Couple of possibilities : You need to add the @EnableJpaRepositories(basePackages = {"your.pkg.here"}) to the Application . This tells Spring Data to look for your repository classes under the specified package.

Akash
  • 587
  • 5
  • 12
0

For me , removing @Primary on multiple Data sources, which was added by mistake fixed the issue

omkar sirra
  • 696
  • 10
  • 28
-6

it was caused by your ide software,set up these options enter image description here

D.Mummy
  • 27
  • 3