Spring Boot(MVC+Hibernate)项目获取Session Factory时遇循环依赖与Bean缺失问题的咨询
先帮你梳理下问题的核心:你遇到的循环依赖和Bean找不到问题,本质是手动重复定义了Spring Boot已经自动配置的组件,打乱了框架的自动装配逻辑。下面一步步拆解解决:
问题根源分析
最初的
entityManagerFactory找不到错误:
Spring Boot的spring-boot-starter-data-jpa依赖会自动帮你配置EntityManagerFactory(Hibernate实现下它就是SessionFactory的实例),你不需要手动定义。这个错误大概率是你的项目依赖缺失,或者application配置有误,导致自动装配未触发。手动添加
entityManagerFactory后引发循环依赖:
你在SecurityConfig里定义了sessionFactoryBean,而SecurityConfig依赖UserDetailsServiceImpl,UserDetailsServiceImpl依赖UserDAO(JPA Repository),UserDAO又依赖EntityManagerFactory——这就形成了SecurityConfig → UserDetailsServiceImpl → UserDAO → EntityManagerFactory(在SecurityConfig内)的闭环循环,触发了Spring的循环依赖禁止机制。
解决方案步骤
1. 移除手动定义的entityManagerFactory Bean
直接删掉SecurityConfig里的sessionFactory方法,让Spring Boot的自动配置接管:
@Configuration @EnableWebSecurity @EnableTransactionManagement public class SecurityConfig extends WebSecurityConfigurerAdapter { private final UserDetailsService userDetailsService; private Environment env; @Autowired public SecurityConfig(@Qualifier("userDetailsServiceImpl") UserDetailsService userDetailsService, Environment env) { this.userDetailsService = userDetailsService; this.env = env; } // 保留你的安全配置(比如configure(HttpSecurity)、passwordEncoder等),移除sessionFactory相关代码 }
2. 确保依赖与配置正确
检查依赖:确认你的
pom.xml(或build.gradle)中引入了spring-boot-starter-data-jpa:
Maven:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>Gradle:
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'检查application配置:确保数据库和JPA配置正确,示例
application.properties:# 数据库连接 spring.datasource.url=jdbc:mysql://localhost:3306/your_database_name spring.datasource.username=your_db_username spring.datasource.password=your_db_password # JPA/Hibernate配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
3. 正确获取SessionFactory
如果你的业务需要直接使用Hibernate的SessionFactory,不需要手动创建,直接注入即可——因为Spring Boot自动配置的EntityManagerFactory就是HibernateSessionFactory的实现:
@Repository public class UserDAOImpl implements UserDAO { private final SessionFactory sessionFactory; // 直接注入Spring Boot自动配置的SessionFactory @Autowired public UserDAOImpl(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } @Override public User getByEmail(String email) { return sessionFactory.getCurrentSession() .createQuery("FROM User u WHERE u.email = :email", User.class) .setParameter("email", email) .uniqueResult(); } }
或者更推荐使用JPA标准的EntityManager(更符合Spring Data JPA的设计):
@Repository public class UserDAOImpl implements UserDAO { private final EntityManager entityManager; @Autowired public UserDAOImpl(EntityManager entityManager) { this.entityManager = entityManager; } @Override public User getByEmail(String email) { return entityManager.createQuery("FROM User u WHERE u.email = :email", User.class) .setParameter("email", email) .uniqueResult(); } }
最后验证
做完以上修改后,重启应用:
- 循环依赖问题会消失,因为不再有闭环的Bean依赖
entityManagerFactory会由Spring Boot自动创建,UserDetailsServiceImpl的构造注入也能正常获取UserDAO
内容的提问来源于stack exchange,提问作者kqlqk

