Spring Boot with 2 database configs - lazy loading with second config does not work
Asked Answered
N

3

4

I have Spring Boot project with 2 database configs.

Primary DB config:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(transactionManagerRef = "primaryTransactionManager", entityManagerFactoryRef = "primaryEntityManagerFactory", basePackages = { "com.example.repository.primary" })
public class PrimaryDbConfig {

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

    @Primary
    @Bean(name = "primaryEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,         @Qualifier("primaryDataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("com.example.domain.primary").persistenceUnit("primary-persistence-unit").build();
    }

    @Primary
    @Bean(name = "primaryTransactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("primaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
} 

And secondary:

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "secondaryEntityManagerFactory", transactionManagerRef = "secondaryTransactionManager", basePackages = { "com.example.repository.secondary" })
public class SecondaryDbConfig {

    @Bean(name = "secondaryDataSource")
    @ConfigurationProperties(prefix = "spring.secondary.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "secondaryEntityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder,         @Qualifier("secondaryDataSource") DataSource dataSource) {
        return builder.dataSource(dataSource).packages("com.example.domain.secondary").persistenceUnit("secondary-persistence-unit").build();
    }

    @Bean(name = "secondaryTransactionManager")
    public PlatformTransactionManager transactionManager(@Qualifier("secondaryEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

There is entity which is loaded with second DB:

@Entity
@Table(name = "users")
public class User {

    @OneToMany(mappedBy = "user")
    private List<Company> companies;

Using:

public interface UserRepository extends JpaRepository<User, Long> {
    User findByEmail(String email);
}

When I use UserRepository, User is retrieved but when I hit to load companies, I get com.sun.jdi.InvocationException occurred invoking method. - com.sun.jdi.InvocationException occurred invoking method. If I change SecondaryDbConfig to @Primary or add fetch = FetchType.EAGER then companies are retrieved as expected. I have tried adding @Transactional(transactionManager="secondaryTransactionManager") but it didn't help.

What did I miss? What's the proper approach to lazy load entity properties when using not primary database config?

Nanananak answered 24/1, 2018 at 14:10 Comment(4)
Do you add fetch eager to primary ? Does it work properly then. In the repository how do you tell it to use the secondary db config?Soriano
Lazy loading works well when I change secondary DB config to @Primary. In repository I don't specify anything except query methods. Config should specify which DB, transaction manager, entity manager should be used in specific package.Nanananak
@JustinasJakavonis May I know, how did you fix this issue, we are facing same issueAlkalinity
@Alkalinity - don't rememberNanananak
A
2

I have resolved this issue by adding @Transactional over @Service class.

Alkalinity answered 1/6, 2022 at 3:11 Comment(2)
Did you need to specify transactionManager?Nanananak
no.. transactionManager we specified package level..Alkalinity
L
0

I was facing a similar issue. To enable lazy loading of JPA entity with multiple databases, you need to create seperate OpenEntityManagerInViewFilter beans for each database in your DBConfig classes. I found the solution here: spring-boot-jpa-multiple-data-sources Search for the term "Lazy" in the article above.

Lapland answered 1/9, 2021 at 19:16 Comment(0)
U
-1

Try to add @Transactional to your @Service method(s) or controller which retrieved list of company.

Good luck!

Unconnected answered 30/6, 2018 at 11:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.