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
相关产品推荐
相关产品推荐

