@EnableJpaRepositories annotation disables data.sql initialization script
My Spring Boot (v2.3.4) based application uses my custom library containing core entities and business logic. To use entities and repositories from this library I had to use @EnableJpaRepositories
and @EntityScan
annotations with proper packages provided.
I also wanted to initialize database with some required data (let's say the configuration) during application startup. I found that Spring Boot allows to use data.sql
or data-${platform}.sql
files to achieve that.
Long story short when using @EnableJpaRepositories
annotation the data.sql
script is not executed.
I did some digging in the code and found that when @EnableJpaRepositories
annotation is not used then entityManagerFactory
bean is of org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean
type. This bean uses org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher
bean post processor, which fires org.springframework.boot.autoconfigure.jdbc.DataSourceSchemaCreatedEvent
event indicating the schema has been created. Class, which listens for this event is org.springframework.boot.autoconfigure.jdbc.DataSourceInitializerInvoker
. This listener invokes initSchema()
method from org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer
class. This method is responsible for whole initialization using data.sql
script.
It looks like setting @EnableJpaRepositories
annotation creates instance of different class for entityManagerFactory
bean, which does not support this simple initialization.
My basic question is then how to make it all work with @EnableJpaRepositories
annotation. I can always use Hibernate's import.sql
file (which works fine) but I'm also trying to understand what exactly is going on under the hood I how can I control it.
UPDATE 1 28.09.2021
I did further investigation and @EnableJpaRepositories
annotation does not change the instance type of entityManagerFactory
but it causes silent exception (?) when creating org.springframework.scheduling.annotation.ProxyAsyncConfiguration
bean (during creation of org.springframework.context.annotation.internalAsyncAnnotationProcessor
bean). It looks like everything is related to @EnableAsync
annotation, which I'm also using but didn't know it might be related. But it is - removing it makes the initialization work even with @EnableJpaRepositories
.
UPDATE 2 28.09.2021
I've found full explanation for my issue. There are 4 conditions, which must be met to reproduce the issue:
@EnableJpaRepositories
annotation in application configuration@EnableAsync
annotation in application configuration- Configuration implements
AsyncConfigurer
interface - Autowired any
JpaRepository
repository or any other bean which injects repository
Enabling asynchronous execution and implementing AsyncConfigurer
makes the whole configuration to be instantiated before regular beans. Because Spring has to inject repository, it needs to instantiate entityManagerFactory
bean too. Spring prints thenINFO
level logs like below:
Bean 'entityManagerFactoryBuilder' of type [org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
One of not eligible BeanPostProcessors
is DataSourceInitializedPublisher
responsible for firing DataSourceSchemaCreatedEvent
event. Without that event, data-${platform}.sql
script won't be processed at all.
I'm not sure what is the role of @EnableJpaRepositories
in that process but without it the problem does not occur.
Example
Minimal code to reproduce the issue (data.sql
located in src/main/resources
):
@Entity
public FileStore {
...
}
public interface FileStoreRepository extends extends JpaRepository<FileStore, Long> {
}
@Configuration
@EnableAsync
@EnableJpaRepositories
public class Configuration implements AsyncConfigurer {
@Autowired
private FileStoreRepository fileStoreRepository;
...
}
Solutions
There are two solutions I'm aware of:
- Move
AsyncConfigurer
along with its overrided methods and@EnableAsync
annotation to separate configuration class - Use
@Lazy
annotation on autowired bean like below:
@Lazy
@Autowired
private FileStoreRepository fileStoreRepository;
Similar problem was pointed by @Allen D. Ball and can be checked there.
from Recent Questions - Stack Overflow https://ift.tt/3AQZavO
https://ift.tt/eA8V8J
Comments
Post a Comment