手动配置DataSource后全应用出现LazyInitializationException问题
手动配置JPA组件(EntityManagerFactory、TransactionManager)后,Spring Boot自动配置的OpenSessionInViewFilter默认只会绑定到名为entityManagerFactory的默认Bean,而你自定义的EntityManagerFactory Bean名称是mainEntityManagerFactory,导致OSIV过滤器和业务代码使用的不是同一个EntityManagerFactory,会话无法在视图层保持打开,最终触发LazyInitializationException。
从启动日志能看到,系统初始化了两个EntityManagerFactory(对应HikariPool-1和HikariPool-2):第一个是Spring Boot自动配置的默认实例,第二个是你自定义的mainEntityManagerFactory。OSIV过滤器绑定到了第一个默认实例,但你的Repository通过@EnableJpaRepositories指定了使用mainEntityManagerFactory,两者不匹配,懒加载自然失效。
有两种简单的修复方式,任选其一即可:
方案1:显式配置OSIV过滤器绑定自定义EntityManagerFactory
添加一个Filter配置类,手动注册OpenEntityManagerInViewFilter并指定使用你的mainEntityManagerFactory:
@Configuration public class OsivFilterConfig { @Autowired @Qualifier("mainEntityManagerFactory") private EntityManagerFactory mainEntityManagerFactory; @Bean public FilterRegistrationBean<OpenEntityManagerInViewFilter> openEntityManagerInViewFilter() { FilterRegistrationBean<OpenEntityManagerInViewFilter> registrationBean = new FilterRegistrationBean<>(); OpenEntityManagerInViewFilter filter = new OpenEntityManagerInViewFilter(); filter.setEntityManagerFactory(mainEntityManagerFactory); registrationBean.setFilter(filter); // 设置过滤器优先级,确保在其他业务过滤器之前执行 registrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE); return registrationBean; } }
方案2:将自定义EntityManagerFactory标记为Primary
在你的mainEntityManagerFactory方法上添加@Primary注解,让Spring Boot自动配置的OSIV过滤器优先使用这个实例:
@Bean @Primary // 添加这个注解 public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory() { // 原代码保持不变 LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setDataSource(dataSource()); factory.setPackagesToScan("org.crm"); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); Properties properties = new Properties(); properties.put("hibernate.physical_naming_strategy", "org.hibernate.boot.model.naming.CamelCaseToUnderscoresNamingStrategy"); properties.put("hibernate.implicit_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy"); factory.setJpaProperties(properties); return factory; }
注意:如果你的项目中存在多个EntityManagerFactory,标记@Primary时要确保不会影响其他数据源的配置逻辑。
内容的提问来源于stack exchange,提问作者Lucas Amaral

