集成Liquibase遇循环依赖错误:entityManagerFactory与liquibase互依赖
Liquibase集成Spring Boot出现循环依赖问题
问题描述
将Liquibase集成到Spring Boot项目后,启动时触发循环依赖错误,liquibase与entityManagerFactory互相依赖。
异常信息
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Failed to initialize dependency 'liquibase' of LoadTimeWeaverAware bean 'entityManagerFactory': Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Circular depends-on relationship between 'liquibase' and 'entityManagerFactory' at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:326) ~[spring-beans-6.1.10.jar:6.1.10] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:952) ~[spring-context-6.1.10.jar:6.1.10] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) ~[spring-context-6.1.10.jar:6.1.10] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.1.jar:3.3.1] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.1.jar:3.3.1] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.1.jar:3.3.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.1.jar:3.3.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.1.jar:3.3.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.1.jar:3.3.1] at sps.SpsBackendApplication.main(SpsBackendApplication.java:26) ~[classes/:na] at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na] at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na] at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-3.3.1.jar:3.3.1] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'liquibase' defined in class path resource [org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]: Circular depends-on relationship between 'liquibase' and 'entityManagerFactory' at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:308) ~[spring-beans-6.1.10.jar:6.1.10] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar:6.1.10] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:313) ~[spring-beans-6.1.10.jar:6.1.10] ... 13 common frames omitted
父pom.xml配置
... <properties> <java.version>21</java.version> <jib-maven.version>3.4.2</jib-maven.version> <maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version> <mapstruct.version>1.5.5.Final</mapstruct.version> <lombok.version>1.18.34</lombok.version> </properties> <modules> <module>backend</module> <module>frontend</module> </modules> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>${junit-jupiter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.liquibase.ext</groupId> <artifactId>liquibase-hibernate6</artifactId> <version>4.29.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>${mockito.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${mapstruct.version}</version> </dependency> <dependency> <groupId>wf.garnier</groupId> <artifactId>testcontainers-dex</artifactId> <version>${testcontainers.dex.version}</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <annotationProcessorPaths> <path> <artifactId>lombok</artifactId> <groupId>org.projectlombok</groupId> <version>${lombok.version}</version> </path> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${mapstruct.version}</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build> ...
子pom.xml配置
.... <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.liquibase.ext</groupId> <artifactId>liquibase-hibernate6</artifactId> </dependency> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc11</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.6.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>wf.garnier</groupId> <artifactId>testcontainers-dex</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> </dependencies> ...
已尝试的自定义配置
LiquibaseConfig
@Configuration public class LiquibaseConfig { @Bean @Lazy public SpringLiquibase liquibase() { SpringLiquibase liquibase = new SpringLiquibase(); // Configure your Liquibase properties here liquibase.setChangeLog("classpath:db/changelog/db.changelog-master.xml"); liquibase.setDataSource(dataSource()); return liquibase; } @Bean public DataSource dataSource() { return new HikariDataSource(); } }
JpaConfig
@Configuration public class JpaConfig { @Bean @DependsOn("liquibase") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(dataSource()); factoryBean.setPackagesToScan("com.example.yourpackage"); factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); return factoryBean; } @Bean public DataSource dataSource() { return new HikariDataSource(); } }
解决方案
方案1:强制指定初始化顺序
在application.properties中添加配置,让JPA延迟初始化,确保Liquibase先执行:
spring.jpa.defer-datasource-initialization=true spring.liquibase.enabled=true
方案2:完全自定义配置,排除自动配置类
- 在启动类排除自动配置:
@SpringBootApplication(exclude = {HibernateJpaAutoConfiguration.class, LiquibaseAutoConfiguration.class}) public class SpsBackendApplication { public static void main(String[] args) { SpringApplication.run(SpsBackendApplication.class, args); } }
- 统一数据源配置:
@Configuration public class DataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource") public DataSource dataSource() { return DataSourceBuilder.create().type(HikariDataSource.class).build(); } }
- 修正Liquibase配置,注入统一数据源:
@Configuration public class LiquibaseConfig { private final DataSource dataSource; public LiquibaseConfig(DataSource dataSource) { this.dataSource = dataSource; } @Bean public SpringLiquibase liquibase() { SpringLiquibase liquibase = new SpringLiquibase(); liquibase.setChangeLog("classpath:db/changelog/db.changelog-master.xml"); liquibase.setDataSource(dataSource); return liquibase; } }
- 修正JPA配置,依赖Liquibase并注入统一数据源:
@Configuration @DependsOn("liquibase") public class JpaConfig { private final DataSource dataSource; public JpaConfig(DataSource dataSource) { this.dataSource = dataSource; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean(); factoryBean.setDataSource(dataSource); factoryBean.setPackagesToScan("sps"); // 替换为你的实体类包路径 factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Properties jpaProperties = new Properties(); jpaProperties.put("hibernate.hbm2ddl.auto", "none"); // 禁用Hibernate自动建表 factoryBean.setJpaProperties(jpaProperties); return factoryBean; } @Bean public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { return new JpaTransactionManager(entityManagerFactory); } }
方案3:移除liquibase-hibernate6依赖
如果不需要Liquibase与Hibernate的实体对比功能,替换为核心Liquibase依赖:
<dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> </dependency>
移除原有的liquibase-hibernate6依赖,该扩展会导致Liquibase依赖EntityManagerFactory,进而引发循环依赖。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

