Hibernate 5.1.0中自定义MyJsonType类找不到的问题求助
解决Hibernate 5.1.0中自定义MyJsonType类找不到的问题
我来帮你拆解这个问题,从类加载、自定义类型实现到Hibernate与JPA的配置差异,一步步解决:
1. 先搞定ClassNotFoundException的核心原因
这个错误本质是Hibernate找不到你的自定义类型类,大概率是配置或类加载路径的问题:
- 必须用全类名:在实体类的
@Type注解里,不能只写MyJsonType,要写完整包路径,比如com.yourproject.types.MyJsonType。JPA可能默认扫描了你的包,但Hibernate API需要更明确的类定位。 - 确认类已编译:执行
mvn clean compile,检查target/classes目录下是否存在MyJsonType.class文件,确保Maven正确编译了这个类。 - 显式注册自定义类型:如果用
hibernate.cfg.xml配置SessionFactory,要添加<mapping class="com.yourproject.types.MyJsonType"/>;如果是编程式配置,要在Configuration里调用cfg.addAnnotatedClass(MyJsonType.class),让Hibernate知道这个类型的存在。
2. 完成MyJsonType的必要实现(针对Hibernate 5.1.0)
你还没写完这个类,Hibernate 5.1.x的自定义用户类型需要实现UserType接口,下面是适配PostgreSQL JSONB的核心代码模板:
import org.hibernate.HibernateException; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.type.UserType; import org.postgresql.util.PGobject; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import java.util.Map; public class MyJsonType implements UserType { // 对应PostgreSQL的jsonb类型 @Override public int[] sqlTypes() { return new int[]{Types.JAVA_OBJECT}; } // 指定要映射的Java类型,这里用Map示例,也可以换成你的自定义POJO @Override public Class returnedClass() { return Map.class; } @Override public boolean equals(Object x, Object y) throws HibernateException { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); } // 实现JSON对象的深拷贝,用Jackson处理 @Override public Object deepCopy(Object value) throws HibernateException { if (value == null) return null; ObjectMapper mapper = new ObjectMapper(); try { return mapper.readValue(mapper.writeValueAsString(value), returnedClass()); } catch (IOException e) { throw new HibernateException("JSON深拷贝失败", e); } } @Override public boolean isMutable() { return true; // JSON对象是可变的 } // 从ResultSet读取JSONB数据转成Java对象 @Override public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner) throws HibernateException, SQLException { PGobject pgObject = (PGobject) rs.getObject(names[0]); if (pgObject == null || pgObject.getValue() == null) { return null; } ObjectMapper mapper = new ObjectMapper(); try { return mapper.readValue(pgObject.getValue(), returnedClass()); } catch (IOException e) { throw new HibernateException("解析JSONB失败", e); } } // 把Java对象转成PGobject写入数据库(对应jsonb类型) @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session) throws HibernateException, SQLException { if (value == null) { st.setNull(index, Types.OTHER); return; } ObjectMapper mapper = new ObjectMapper(); try { PGobject pgObject = new PGobject(); pgObject.setType("jsonb"); pgObject.setValue(mapper.writeValueAsString(value)); st.setObject(index, pgObject); } catch (IOException e) { throw new HibernateException("序列化JSON到JSONB失败", e); } } // 下面的方法直接默认实现即可 @Override public Object assemble(Serializable cached, Object owner) throws HibernateException { return deepCopy(cached); } @Override public Serializable disassemble(Object value) throws HibernateException { return (Serializable) deepCopy(value); } @Override public Object replace(Object original, Object target, Object owner) throws HibernateException { return deepCopy(original); } @Override public int hashCode(Object x) throws HibernateException { return x != null ? x.hashCode() : 0; } }
另外,要确保pom.xml里引入了兼容的PostgreSQL驱动:
<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>9.4.1212</version> <!-- 和Hibernate 5.1.0适配的版本 --> </dependency>
3. 注意Hibernate API与JPA EntityManager的配置差异
JPA的EntityManager可能通过persistence.xml的<package>或<class>标签自动扫描了你的自定义类型,但Hibernate的SessionFactory不会自动做这件事:
- 如果用xml配置SessionFactory,必须手动添加自定义类型的映射;
- 如果是编程式构建SessionFactory,要显式把自定义类型添加到Configuration中;
- 实体类里的
@Type注解必须用全类名,不能简写。
4. 最后排查依赖冲突
执行mvn dependency:tree查看依赖树,确保没有多个版本的Hibernate核心包共存,版本冲突也可能导致类加载异常。
内容的提问来源于stack exchange,提问作者Sairam Vinjamuri
相关产品推荐
相关产品推荐

