You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:06:05