Liquibase Maven插件集成liquibase-hibernate5时JSONB类加载报错咨询
问题背景
- 运行环境:Liquibase core、liquibase-hibernate5 4.10,Spring Boot 2.5.14
- 目标:适配PostgreSQL JSONB类型,执行
mvn liquibase:diff时正常识别该类型 - 已完成的配置:
- 自定义继承
PostgreSQL10Dialect的方言类,代码如下:public class PostgreSQLDialect extends PostgreSQL10Dialect { public PostgreSQLDialect() { // 注册JSONB列类型,避免liquibase插件执行失败 System.out.println("Registering the JSONB type."); this.registerColumnType(Types.JAVA_OBJECT, "jsonb"); } } - application.yml中指定Hibernate使用自定义方言:
spring.jpa.properties.hibernate.dialect: my.example.PostgreSQLDialect - pom.xml中liquibase插件的
referenceUrl配置指定自定义方言:<referenceUrl>hibernate:spring:my.example.persist?dialect=my.exampple.PostgreSQLDialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl</referenceUrl>
- 自定义继承
- 故障现象:执行
mvn liquibase:diff时,日志显示自定义方言已加载、JSONB类型注册完成,但抛出ClassNotFoundException: Could not load requested class : jsonb异常,此前只能通过注释JSONB相关代码临时规避。完整异常栈如下:Caused by: java.lang.ClassNotFoundException: Could not load requested class : jsonb at org.hibernate.boot.registry.classloading.internal.AggregatedClassLoader.findClass (AggregatedClassLoader.java:210) at java.lang.ClassLoader.loadClass (ClassLoader.java:589) at java.lang.ClassLoader.loadClass (ClassLoader.java:522) at java.lang.Class.forName0 (Native Method) at java.lang.Class.forName (Class.java:427) at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName (ClassLoaderServiceImpl.java:130) at org.hibernate.boot.internal.ClassLoaderAccessImpl.classForName (ClassLoaderAccessImpl.java:67) at org.hibernate.cfg.annotations.SimpleValueBinder.fillSimpleValue (SimpleValueBinder.java:536) at org.hibernate.cfg.SetSimpleValueTypeSecondPass.doSecondPass (SetSimpleValueTypeSecondPass.java:25) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses (InFlightMetadataCollectorImpl.java:1693) at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses (InFlightMetadataCollectorImpl.java:1651) at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete (MetadataBuildingProcess.java:295) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata (EntityManagerFactoryBuilderImpl.java:1224) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build (EntityManagerFactoryBuilderImpl.java:1255) at liquibase.ext.hibernate.database.HibernateEjb3Database.buildMetadataFromPath (HibernateEjb3Database.java:59) at liquibase.ext.hibernate.database.HibernateDatabase.buildMetadata (HibernateDatabase.java:143) at liquibase.ext.hibernate.database.HibernateDatabase.setConnection (HibernateDatabase.java:83) .....
故障原因
- 配置存在笔误:
referenceUrl中配置的方言类路径为my.exampple.PostgreSQLDialect,多写了一个字母p,和实际类路径my.example.PostgreSQLDialect不匹配。 - 方言配置不完整:仅通过
registerColumnType注册JDBC类型到SQL列类型的映射,只能解决SQL生成阶段的类型识别问题。Hibernate解析实体类上的@Type(type = "jsonb")注解时,会将jsonb作为类名尝试加载,找不到对应的Hibernate Type实现就会抛出类不存在异常。
解决步骤
- 修正pom.xml中
referenceUrl的方言类名笔误,将my.exampple.PostgreSQLDialect改为实际的全限定类名my.example.PostgreSQLDialect。 - 补全JSONB类型的Hibernate注册逻辑,可直接使用成熟的hibernate-types实现,也可自定义UserType:
- 引入适配Hibernate 5.4+版本的hibernate-types依赖:
<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>2.14.0</version> </dependency> - 修改自定义方言类,补充Hibernate类型注册:
import com.vladmihalcea.hibernate.type.json.JsonBinaryType; import org.hibernate.dialect.PostgreSQL10Dialect; import java.sql.Types; public class PostgreSQLDialect extends PostgreSQL10Dialect { public PostgreSQLDialect() { super(); // 注册JDBC类型到JSONB列类型的映射 this.registerColumnType(Types.JAVA_OBJECT, "jsonb"); // 注册Hibernate类型,绑定jsonb标识到JsonBinaryType实现类 this.registerHibernateType(Types.OTHER, JsonBinaryType.class.getName()); } } - 在使用JSONB类型的实体类上添加类型定义,明确jsonb标识对应的实现类:
import com.vladmihalcea.hibernate.type.json.JsonBinaryType; import org.hibernate.annotations.Type; import org.hibernate.annotations.TypeDef; import javax.persistence.Column; import javax.persistence.Entity; @Entity @TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) public class YourEntity { // 其他实体字段 @Type(type = "jsonb") @Column(columnDefinition = "jsonb") private YourJsonDto jsonConfigField; }
- 引入适配Hibernate 5.4+版本的hibernate-types依赖:
- 执行
mvn clean liquibase:diff验证,异常即可消除。
注:如果不希望引入第三方依赖,可自行实现org.hibernate.usertype.UserType接口完成JSONB类型的序列化、反序列化逻辑,注册流程和上述一致。
内容的提问来源于stack exchange,提问作者edbras
相关产品推荐
相关产品推荐

