已解决:Java Hibernate QuerySyntaxException:类未映射问题
解决Hibernate QuerySyntaxException: Class is not mapped 错误
问题背景
作为Hibernate新手,开发宿舍管理桌面应用时,已创建并填充hostel_db MySQL数据库,尝试执行查询from Hostel时抛出QuerySyntaxException: Class is not mapped错误,数据库连接正常,但无法识别实体类。
错误根源
原ConnectionUtils类中,Hibernate配置仅加载了hibernate.cfg.xml,但未显式添加实体类到配置中,导致Hibernate无法映射实体与数据库表的关联。
修正后的ConnectionUtils类
public class ConnectionUtils { private static Map<String, String> databaseProperties = new HashMap<>(); private static Configuration databaseConfiguration = new Configuration(); private static final String dialect = "org.hibernate.dialect.MySQL5Dialect"; private static final String url = "jdbc:mysql://localhost:3306/".concat(ConnectionData.getDbName()); private static final String driver = "com.mysql.cj.jdbc.Driver"; private static EntityManagerFactory emf; private static SessionFactory sessionFactory; public ConnectionUtils(){} public void setUpProperties() { propertiesSetup(ConnectionData.getUsr(), ConnectionData.getPsw()); StandardServiceRegistryBuilder standardServiceRegistryBuilder = new StandardServiceRegistryBuilder(). applySettings(databaseConfiguration.getProperties()); emf = Persistence.createEntityManagerFactory(ConnectionData.getTablesPackage(), databaseProperties); sessionFactory = databaseConfiguration.buildSessionFactory(standardServiceRegistryBuilder.build()); } public EntityManagerFactory getEntityManagerFactory() { return emf; } public SessionFactory getSessionFactory() { return sessionFactory; } private static void propertiesSetup(String username, String password) { // 加载hibernate.cfg.xml配置 try { databaseConfiguration.configure(). setProperty("hibernate.connection.username", username). setProperty("hibernate.connection.password", password); } catch (HibernateException e) { if (verifyHibernateConfigXml()) throw new RuntimeException("hibernate.cfg.xml格式错误"); } persistenceSetup(username, password); } private static boolean verifyHibernateConfigXml() { try { InputStream is = ConnectionUtils.class.getClassLoader().getResourceAsStream("hibernate.cfg.xml"); return true; } catch (NullPointerException npe) { throw new RuntimeException("hibernate.cfg.xml不存在"); } } private static void persistenceSetup(String username, String password) { // 自动扫描包下的实体类并添加到配置 try { for (Class cls : getEntityClassesFromPackage(ConnectionData.getTablesPackage())) { databaseConfiguration.addAnnotatedClass(cls); } } catch (Exception ex) { ex.printStackTrace(); } // 设置数据库连接属性 databaseProperties.put("hibernate.connection.driver_class", driver); databaseProperties.put("hibernate.connection.url", url); databaseProperties.put("hibernate.connection.autocommit", "false"); databaseProperties.put("hibernate.connection.username", username); databaseProperties.put("hibernate.connection.password", password); databaseProperties.put("hibernate.dialect", dialect); databaseProperties.put("hibernate.connection.CharSet", "utf8"); databaseProperties.put("hibernate.connection.characterEncoding", "utf8"); databaseProperties.put("hibernate.connection.useUnicode", "true"); databaseProperties.put("hibernate.show_sql", "true"); databaseProperties.put("hibernate.hbm2ddl.auto", "update"); } // 扫描指定包下的所有类 private static List<Class<?>> getEntityClassesFromPackage(String packageName) throws ClassNotFoundException, URISyntaxException { List<String> classNames = getClassNamesFromPackage(packageName); List<Class<?>> classes = new ArrayList<Class<?>>(); for (String className : classNames) { Class<?> cls = Class.forName(packageName + "." + className); // 筛选带有@Entity注解的类 for (Annotation annotation : cls.getAnnotations()) { if (annotation instanceof javax.persistence.Entity) { classes.add(cls); } } } return classes; } // 获取指定包下的所有类名 private static ArrayList<String> getClassNamesFromPackage(String packageName) throws URISyntaxException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ArrayList<String> names = new ArrayList<String>(); packageName = packageName.replace(".", "/"); URL packageURL = classLoader.getResource(packageName); URI uri = new URI(packageURL.toString()); File folder = new File(uri.getPath()); File[] files = folder.listFiles(); for (File file: files) { String name = file.getName(); name = name.substring(0, name.lastIndexOf('.')); // 移除.class后缀 names.add(name); } return names; } }
额外说明
- MySQL驱动更新:将原驱动
com.mysql.jdbc.Driver替换为com.mysql.cj.jdbc.Driver,适配新版MySQL驱动规范。 - 实体类自动扫描:新增包扫描逻辑,自动识别带有
@Entity注解的实体类并添加到Hibernate配置,避免手动添加实体类的繁琐操作。 - Main类调用调整:原静态方法改为实例方法,调用方式需修改为:
public class Main { public static void main(String[] args) { ConnectionUtils connUtils = new ConnectionUtils(); connUtils.setUpProperties(); // 获取SessionFactory和EntityManager SessionFactory sessionFactory = connUtils.getSessionFactory(); EntityManager em = connUtils.getEntityManagerFactory().createEntityManager(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Query query = session.createQuery("from Hostel"); List<?> list = query.getResultList(); Hostel hostel = (Hostel) list.get(0); System.out.println("\nHostel: \n" + hostel); transaction.commit(); session.close(); em.close(); } }
内容的提问来源于stack exchange,提问作者Antonino
相关产品推荐
相关产品推荐

