Spring配置HibernateTemplate触发上下文初始化异常求助
问题描述
使用Java配置HibernateTemplate Bean时触发上下文初始化异常,数据库表已成功创建,但Bean配置存在问题,核心异常为org.hibernate.criterion.Criterion类未找到,已尝试更换Hibernate依赖版本但无效。
相关代码
1. Student实体类
package com.spring.orm.Entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; @Entity @Table(name = "student") public class Student { @Id @Column(name = "student_id") private long studentId; @Column(name = "student_name") private String studentName; @Column(name = "student_city") private String studentCity; public long getStudentId() { return studentId; } public void setStudentId(long studentId) { this.studentId = studentId; } public String getStudentName() { return studentName; } public void setStudentName(String studentName) { this.studentName = studentName; } public String getStudentCity() { return studentCity; } public void setStudentCity(String studentCity) { this.studentCity = studentCity; } public Student() { } public Student(long studentId, String studentName, String studentCity) { this.studentId = studentId; this.studentName = studentName; this.studentCity = studentCity; } }
2. Student Dao接口
package com.spring.orm.Dao; import com.spring.orm.Entity.Student; public interface StudentDao { public Student insert(Student student); }
3. Student Dao实现类
package com.spring.orm.Dao.Impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.orm.hibernate5.HibernateTemplate; import com.spring.orm.Dao.StudentDao; import com.spring.orm.Entity.Student; public class StudentDaoImpl implements StudentDao{ @Autowired private HibernateTemplate hibernateTemplate; @Override public Student insert(Student student) { Student st = (Student) hibernateTemplate.save(student); return st; } }
4. Hibernate配置类
package com.spring.orm.Config; import java.util.Properties; import javax.sql.DataSource; import org.hibernate.SessionFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate5.HibernateTemplate; import org.springframework.orm.hibernate5.HibernateTransactionManager; import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import com.spring.orm.Dao.Impl.StudentDaoImpl; @Configuration @EnableTransactionManagement public class HibernateConfig { @Bean public Properties getHibernateProperties(){ Properties properties = new Properties(); properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL8Dialect"); properties.setProperty("hibernate.show_sql", "true"); properties.setProperty("hibernate.hbm2ddl.auto", "update"); System.out.println("Configured Hibernate properties"); return properties; } @Bean public DriverManagerDataSource getDataSource(){ DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/springjdbc"); dataSource.setUsername("root"); dataSource.setPassword("qwsx##HG##123"); System.out.println("Configured datasource"); return dataSource; } @Bean public LocalSessionFactoryBean getSessionFactory(){ LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean(); sessionFactory.setDataSource(getDataSource()); sessionFactory.setHibernateProperties(getHibernateProperties()); sessionFactory.setPackagesToScan("com.spring.orm.Entity"); System.out.println("Configured session factory"); return sessionFactory; } @Bean(name = "hibernateTemplate") public HibernateTemplate getHibernateTemplate(){ HibernateTemplate hibernateTemplateObj = new HibernateTemplate(); hibernateTemplateObj.setSessionFactory(getSessionFactory().getObject()); return hibernateTemplateObj; } @Bean public HibernateTransactionManager transactionManager() { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(getSessionFactory().getObject()); return transactionManager; } @Bean(name = "studentImpl") public StudentDaoImpl getStudentDao(){ StudentDaoImpl studentDaoImpl = new StudentDaoImpl(); return studentDaoImpl; } }
5. 启动类App.java
package com.spring.orm; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import com.spring.orm.Config.HibernateConfig; import com.spring.orm.Dao.StudentDao; import com.spring.orm.Entity.Student; public class App { public static void main( String[] args ) { System.out.println( "Application started!" ); ApplicationContext context = new AnnotationConfigApplicationContext(HibernateConfig.class); StudentDao stDaoObj = context.getBean("studentImpl", StudentDao.class); Student st = new Student(); st.setStudentId(44); st.setStudentName("Harshit Gupta"); st.setStudentCity("Karera"); stDaoObj.insert(st); } }
6. Pom.xml依赖
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.spring.orm</groupId> <artifactId>springorm</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>springorm</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>6.1.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.1.3</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>6.1.3</version> </dependency> <dependency> <groupId>org.hibernate.orm</groupId> <artifactId>hibernate-core</artifactId> <version>6.1.7.Final</version> </dependency> <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-dbcp</artifactId> <version>9.0.80</version> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.3.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
异常信息
Application started! Configured Hibernate properties Configured datasource Configured session factory Mar 10, 2024 9:04:26 AM org.hibernate.Version logVersion INFO: HHH000412: Hibernate ORM core version 6.1.5.Final Mar 10, 2024 9:04:27 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQL8Dialect Mar 10, 2024 9:04:27 AM org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl logSelectedDialect WARN: HHH90000026: MySQL8Dialect has been deprecated; use org.hibernate.dialect.MySQLDialect instead Mar 10, 2024 9:04:27 AM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] Mar 10, 2024 9:04:27 AM org.springframework.context.support.AbstractApplicationContext refresh WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateTemplate' defined in com.spring.orm.Config.HibernateConfig: Failed to instantiate [org.springframework.orm.hibernate5.HibernateTemplate]: Factory method 'getHibernateTemplate' threw exception with message: org/hibernate/criterion/Criterion Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateTemplate' defined in com.spring.orm.Config.HibernateConfig: Failed to instantiate [org.springframework.orm.hibernate5.HibernateTemplate]: Factory method 'getHibernateTemplate' threw exception with message: org/hibernate/criterion/Criterion at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:485) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1164) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:561) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:521) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:325) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:323) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:959) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) at org.springframework.context.annotation.AnnotationConfigApplicationContext.<init>(AnnotationConfigApplicationContext.java:93) at com.spring.orm.App.main(App.java:20) Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.orm.hibernate5.HibernateTemplate]: Factory method 'getHibernateTemplate' threw exception with message: org/hibernate/criterion/Criterion at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:647) ... 14 more Caused by: java.lang.NoClassDefFoundError: org/hibernate/criterion/Criterion at com.spring.orm.Config.HibernateConfig.getHibernateTemplate(HibernateConfig.java:57) at com.spring.orm.Config.HibernateConfig$$SpringCGLIB$$0.CGLIB$getHibernateTemplate$3(<generated>) at com.spring.orm.Config.HibernateConfig$$SpringCGLIB$$FastClass$$1.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:258) at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:331) at com.spring.orm.Config.HibernateConfig$$SpringCGLIB$$0.getHibernateTemplate(<generated>) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) at java.base/java.lang.reflect.Method.invoke(Method.java:580) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ... 15 more Caused by: java.lang.ClassNotFoundException: org.hibernate.criterion.Criterion at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:526) ... 24 more
解决方案
核心问题原因
org.hibernate.criterion.Criterion是Hibernate 5及之前版本的API,在Hibernate 6中已被移除。当前使用的spring-orm:6.1.3中的hibernate5模块(即HibernateTemplate)是为Hibernate 5设计的,无法兼容Hibernate 6。
具体解决步骤
替换Hibernate依赖为兼容版本
将Hibernate 6依赖替换为Hibernate 5.x版本(与Spring ORM 6.x兼容),同时修改groupId:<!-- Hibernate Core 5.x --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.6.15.Final</version> </dependency>修正SessionFactory获取方式
配置类中直接调用getSessionFactory().getObject()会导致SessionFactory未初始化完成就被获取,改为通过依赖注入传入:@Bean(name = "hibernateTemplate") public HibernateTemplate getHibernateTemplate(SessionFactory sessionFactory){ HibernateTemplate hibernateTemplateObj = new HibernateTemplate(); hibernateTemplateObj.setSessionFactory(sessionFactory); return hibernateTemplateObj; } @Bean public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) { HibernateTransactionManager transactionManager = new HibernateTransactionManager(); transactionManager.setSessionFactory(sessionFactory); return transactionManager; }优化Dao类的Spring管理
在StudentDaoImpl上添加@Repository注解,让Spring自动扫描创建Bean,可删除配置类中的getStudentDao()方法:@Repository public class StudentDaoImpl implements StudentDao{ // 原有代码 }调整方言配置(可选)
Hibernate 5中MySQL8Dialect是合法的,若后续升级到Hibernate 6则需改为org.hibernate.dialect.MySQLDialect。
内容的提问来源于stack exchange,提问作者Harshit Gupta

