SpringBoot+Hibernate5整合报错:BasicDataSource抛出UnsupportedOperationException
我正在搭建一个基于Spring Boot MVC、Hibernate 5的项目(后续部署到GCP),配置完启动类、Web初始化类、Hibernate配置类及相关依赖后,启动时抛出UnsatisfiedDependencyException,最终根源是BasicDataSource抛出UnsupportedOperationException。相关代码、报错信息及依赖配置如下:
代码部分
启动类
@SpringBootApplication @ComponentScan(basePackages = {"com.dirtangel.miodigy"}) public class Main { public static void main(String[] args) { SpringApplication.run(Main.class, args); } }
Web初始化类
public class MyWebAppInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext container) { // 创建根Spring应用上下文 AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext(); rootContext.setConfigLocation("com.dirtangel.miodigy.config"); rootContext.register(HibernateConf.class); // 管理根应用上下文的生命周期 container.addListener(new ContextLoaderListener(rootContext)); // 创建DispatcherServlet的Spring应用上下文 AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext(); dispatcherContext.register(HibernateConf.class); // 注册并映射DispatcherServlet ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext)); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/"); } }
Hibernate配置类
@Configuration @EnableTransactionManagement @PropertySource({"classpath:application.properties"}) @PropertySource({"classpath:hibernate.properties"}) @EntityScan("com.dirtangel.miodigy.entity") @EnableJpaRepositories("com.dirtangel.miodigy.repo") @EnableWebMvc @ComponentScan(basePackages = {"com.dirtangel.miodigy"}) public class HibernateConf implements WebMvcConfigurer, ApplicationContextAware { @Bean public LocalSessionFactoryBean sessionFactory() throws IOException { LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(dataSource()); sessionFactory.setAnnotatedClasses(new Class[]{Hustler.class}); sessionFactory.setConfigLocation(applicationContext.getResource("classpath:hibernate.cfg.xml")); sessionFactory.setPackagesToScan( new String[]{"com.dirtangel.miodigy", "com.dirtangel.miodigy.entity"}); sessionFactory.setHibernateProperties(hibernateProperties()); sessionFactory.afterPropertiesSet(); return sessionFactory; } @Bean(name = "dataSource") public DataSource dataSource() { BasicDataSource dataSource = new BasicDataSource(); dataSource.setDriverClassName("org.postgresql.Driver"); dataSource.setUrl("jdbc:postgresql://localhost:5432/miodigy"); dataSource.setUsername("postgres"); dataSource.setPassword("postgres"); return dataSource; } @Bean public PlatformTransactionManager hibernateTransactionManager() throws IOException { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(sessionFactory().getObject()); return transactionManager; } private Properties hibernateProperties() { Properties hibernateProperties = new Properties(); hibernateProperties.setProperty( "hibernate.hbm2ddl.auto", "create-drop"); hibernateProperties.setProperty( "hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect"); hibernateProperties.setProperty("hibernate.show_sql", "true"); hibernateProperties.setProperty("hibernate.format_sql", "true"); hibernateProperties.setProperty("spring.jpa.hibernate.naming.physical-strategy", "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"); hibernateProperties.setProperty("hibernate.connection.url", "jdbc:postgresql://localhost:5432/miodigy"); hibernateProperties.setProperty("hibernate.connection.username", "postgres"); hibernateProperties.setProperty("hibernate.connection.password", "postgres"); hibernateProperties.setProperty("hibernate.show_sql", "true"); hibernateProperties.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver"); hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect"); hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "update"); hibernateProperties.setProperty("hibernate.packageToScan", "com.dirtangel.miodigy.entity"); hibernateProperties.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false"); return hibernateProperties; } }
报错信息
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'openEntityManagerInViewInterceptorConfigurer' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]: Unsatisfied dependency expressed through method 'openEntityManagerInViewInterceptorConfigurer' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in com.dirtangel.miodigy.HibernateConf: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Factory method 'sessionFactory' threw exception; nested exception is java.lang.UnsupportedOperationException: Not supported by BasicDataSource at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:723) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
依赖配置
<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-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jersey</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </dependency> <dependency> <groupId>nz.net.ultraq.thymeleaf</groupId> <artifactId>thymeleaf-layout-dialect</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <scope>test</scope> <type>jar</type> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- PostgreSQL JDBC驱动依赖 --> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> <!-- Hibernate核心依赖 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.15.Final</version> </dependency>
问题分析与修复方案
核心问题
- 配置冲突:同时使用Spring Boot自动配置和手动
WebApplicationInitializer、LocalSessionFactoryBean配置,导致JPA与原生Hibernate的SessionFactory Bean冲突。 - 数据源依赖缺失:
BasicDataSource属于Apache Commons DBCP组件,当前依赖中未引入该库,调用未实现的方法时抛出异常。 - 配置冗余:
HibernateConf中重复配置Hibernate属性,且同时启用JPA和原生Hibernate配置,加剧冲突。
修复步骤
1. 删除手动Web初始化类
Spring Boot已自动配置DispatcherServlet和上下文,无需自定义MyWebAppInitializer,直接删除该类。
2. 替换数据源实现
使用Spring Boot默认的HikariCP数据源(性能更优),可通过两种方式配置:
方式一:自动配置(推荐)
在application.properties中添加数据源配置,Spring Boot会自动创建HikariDataSource Bean:
spring.datasource.url=jdbc:postgresql://localhost:5432/miodigy spring.datasource.username=postgres spring.datasource.password=postgres spring.datasource.driver-class-name=org.postgresql.Driver
然后删除HibernateConf中的手动dataSource Bean。
方式二:手动配置HikariDataSource
@Bean(name = "dataSource") public DataSource dataSource() { HikariDataSource dataSource = new HikariDataSource(); dataSource.setDriverClassName("org.postgresql.Driver"); dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/miodigy"); dataSource.setUsername("postgres"); dataSource.setPassword("postgres"); return dataSource; }
3. 简化Hibernate配置类
借助spring-boot-starter-data-jpa的自动配置能力,大幅精简配置:
@Configuration @EnableTransactionManagement @PropertySource({"classpath:application.properties"}) @EntityScan("com.dirtangel.miodigy.entity") @EnableJpaRepositories("com.dirtangel.miodigy.repo") public class HibernateConf implements WebMvcConfigurer { // 仅保留自定义的WebMvc配置方法(如有) }
将Hibernate属性迁移至application.properties:
# JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL95Dialect spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
4. 清理冗余依赖
移除重复的Spring核心依赖(spring-core、spring-web、spring-webmvc等已包含在spring-boot-starter-web中),以及未使用的spring-boot-starter-jersey。同时移除手动指定的hibernate-core版本,使用Spring Boot提供的兼容版本,避免版本冲突。
5. 验证启动
完成以上修改后,重新启动项目,即可解决UnsatisfiedDependencyException和UnsupportedOperationException问题。
内容的提问来源于stack exchange,提问作者Maciej Mioduszewski

