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

Hibernate session.get查询Oracle CHAR类型字符串失败问题求助

Oracle CHAR类型与Hibernate String映射的查询匹配问题

环境信息

  • Java 8
  • Hibernate 5.6.15
  • Oracle Database 19c

数据库与实体定义

数据库列定义:

"ACCOUNT_NO" CHAR(16 CHAR)

Hibernate实体类:

public class AcctId implements java.io.Serializable {

    private String accountNo;
    
    @Column(name="ACCOUNT_NO", length=16)
    public String getAccountNo() {
        return this.accountNo;
    }
    
    public void setAccountNo(String accountNo) {
        this.accountNo = accountNo;
    }
     
}

问题现象

当查询长度为16字符的accountNo时,session.get能正常获取到账户;但当accountNo长度小于16时,即使账户存在,session.get也无法返回结果。

原因是Oracle的CHAR类型会在长度不足时自动填充空格,导致传入的查询参数(无空格)与数据库中存储的带空格值不匹配。

已尝试但无效的方案

方案1:修改@Column注解

使用@Column(name="ACCOUNT_NO", length=16, columnDefinition="CHAR"),未解决问题。

方案2:自定义UserType

实现了TrimmedStringType,但未生效:

public class TrimmedStringType implements UserType {

    private static final int[] SQL_TYPES = { Types.CHAR };

    @Override
    public int[] sqlTypes() {
        return SQL_TYPES;
    }

    @Override
    public Class returnedClass() {
        return String.class;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object deepCopy(Object obj) throws HibernateException {
        if (obj == null) {
        return null;
        }
        return new String((String) obj);
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return (x == y) || (x != null && y != null && (x.equals(y)));
    }

    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner)
        throws HibernateException, SQLException {
        String val = rs.getString(names[0]);
        return val != null ? val.trim() : null;
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session)
        throws HibernateException, SQLException {
        st.setString(index, (String)value);
    }

    public boolean isMutable() {
        return false;
    }

    public Object nullSafeGet(ResultSet rs, String[] names, Object obj) throws HibernateException, SQLException {
        String val = rs.getString(names[0]);
        return val != null ? val.trim() : null;
    }

    public void nullSafeSet(PreparedStatement pstmt, Object obj, int i) throws HibernateException, SQLException {
        pstmt.setString(i, (String)obj);
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

需求说明

无法修改数据库列类型为VARCHAR2,且有近100个类似的Hibernate实体,手动填充空格过于繁琐,需要在Hibernate层面解决该问题。


内容的提问来源于stack exchange,提问作者Raju

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:04:55