多版本MySQL驱动依赖配置与HikariCP+Hibernate使用问题排查
首先,我们来拆解你遇到的几个核心问题,然后一步步解决:
1. Maven依赖的错误与冲突
你pom.xml里的第二个依赖犯了一个低级错误:groupId写成了mysql.(多了个句号),这会导致Maven无法正确识别这个依赖。即使修正了这个问题,同时引入两个版本的MySQL驱动也会引发类加载冲突——Maven的依赖调解机制会自动选择一个版本(通常是更新的8.0.21),另一个版本的类可能无法被正确加载。
最优解决方案:用MySQL 8驱动向下兼容
MySQL 8.0的官方驱动(mysql-connector-java 8.x版本)是向下兼容MySQL 5.6及以上版本的,所以你完全可以只保留8.0.21的驱动,同时连接MySQL 5和8,这样彻底避免依赖冲突:
<!-- 只保留这一个依赖即可 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.21</version> </dependency>
如果你因为特殊原因必须使用对应版本的驱动,那需要通过类加载器隔离(比如Java模块、自定义类加载器)来分隔两个版本的驱动类,这会复杂很多,不推荐。
2. 驱动类与数据库配置的对应问题
你遇到的hibernate.connection.driver_class错误,核心是驱动类的选择和数据库版本不匹配:
- MySQL 5:传统驱动类是
com.mysql.jdbc.Driver,但在8.x驱动中这个类只是兼容类,实际会代理到com.mysql.cj.jdbc.Driver - MySQL 8:必须使用新的驱动类
com.mysql.cj.jdbc.Driver,而且URL必须指定时区参数(比如serverTimezone=UTC)
同时,Hibernate方言也要对应:
- MySQL 5用
org.hibernate.dialect.MySQL5Dialect - MySQL 8用
org.hibernate.dialect.MySQL8Dialect
3. 为双数据库配置独立的SessionFactory
你当前的代码只能构建一个SessionFactory,但你需要连接两个不同的数据库,所以必须为每个数据库单独创建SessionFactory实例,每个实例对应自己的配置:
重构你的SessionFactory构建代码
// 新增参数DbModel,每个DbModel对应一个数据库的配置 protected SessionFactory buildSessionFactory(DbModel dbModel, List<Class> entityClasses) { StandardServiceRegistry registry = null; StandardServiceRegistryBuilder registryBuilder = new StandardServiceRegistryBuilder(); try { registry = registryBuilder.applySettings(buildDbSettings(dbModel)).build(); MetadataSources metadataSources = new MetadataSources(registry); for (Class<?> entity : entityClasses) { metadataSources.addAnnotatedClass(entity); } Metadata metadata = metadataSources.getMetadataBuilder().build(); return metadata.getSessionFactoryBuilder().build(); } catch (Exception e) { if (registry != null) StandardServiceRegistryBuilder.destroy(registry); System.err.println("SessionFactory创建失败:" + e.getMessage()); throw new ExceptionInInitializerError(e); } } private Map<String, Object> buildDbSettings(DbModel dbModel) { Map<String, Object> settings = new HashMap<>(); // 驱动类根据数据库版本传入正确值 settings.put(Environment.DRIVER, dbModel.getDriver()); // 方言也要对应版本 settings.put(Environment.DIALECT, dbModel.getDialect()); settings.put(Environment.URL, dbModel.getUrl()); settings.put(Environment.USER, dbModel.getUser()); settings.put(Environment.PASS, dbModel.getSecret()); settings.put(Environment.SHOW_SQL, dbModel.getShowSql()); settings.put(Environment.ENABLE_LAZY_LOAD_NO_TRANS, dbModel.getLazyLoad()); // HikariCP连接池配置保持不变 settings.put("hibernate.hikari.connectionTimeout", dbModel.getConnectionTimeout()); settings.put("hibernate.hikari.idleTimeout", dbModel.getIdleTimeout()); settings.put("hibernate.hikari.maxLifetime", dbModel.getMaxLifetime()); settings.put("hibernate.hikari.autoCommit", dbModel.getAutoCommit()); settings.put("hibernate.hikari.minimumIdle", dbModel.getMinimumIdle()); settings.put("hibernate.hikari.maximumPoolSize", dbModel.getMaxPoolSize()); settings.put("hibernate.hikari.registerMbeans", dbModel.getRegisterMbean()); return settings; }
分别配置两个数据库的DbModel
- MySQL 5配置示例:
DbModel mysql5Db = new DbModel(); mysql5Db.setDriver("com.mysql.cj.jdbc.Driver"); // 用8.x驱动的新类,兼容5 mysql5Db.setDialect("org.hibernate.dialect.MySQL5Dialect"); mysql5Db.setUrl("jdbc:mysql://your-mysql5-host:3306/dbname?useSSL=false"); // 其他用户名、密码、连接池参数按需设置 - MySQL 8配置示例:
DbModel mysql8Db = new DbModel(); mysql8Db.setDriver("com.mysql.cj.jdbc.Driver"); mysql8Db.setDialect("org.hibernate.dialect.MySQL8Dialect"); mysql8Db.setUrl("jdbc:mysql://your-mysql8-host:3306/dbname?useSSL=false&serverTimezone=UTC"); // 其他参数按需设置
4. 你的当前错误的直接原因
你设置了com.mysql.jdbc.Driver,但如果Maven实际加载的是8.0.21的驱动,虽然这个类存在,但它是一个过时的兼容类,可能会因为缺少时区配置(MySQL 8要求)或者类加载冲突导致初始化失败。修正驱动类为com.mysql.cj.jdbc.Driver,并为MySQL 8的URL添加时区参数,就能解决这个直接错误。
内容的提问来源于stack exchange,提问作者Nikolay




