如何在Hibernate XML中映射Java String到PostgreSQL smallint列?
解决HBM XML中String类型映射PostgreSQL smallint列的问题
问题原因
你之前的配置无效,是因为type="string"会让Hibernate始终将该属性按字符串类型绑定到SQL参数,不管sql-type设置什么值——sql-type仅用于生成DDL时指定列类型,不会改变参数绑定的类型,所以PostgreSQL会抛出类型不匹配的错误。
解决方案
方案1:自定义Hibernate UserType(推荐)
创建一个自定义类型,实现String与Short(对应PostgreSQL的smallint)的双向转换:
import org.hibernate.HibernateException; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.UserType; import java.io.Serializable; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; public class StringToShortType implements UserType { @Override public int[] sqlTypes() { return new int[]{Types.SMALLINT}; } @Override public Class returnedClass() { return String.class; } @Override public boolean equals(Object x, Object y) { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); } @Override public int hashCode(Object x) { return x.hashCode(); } @Override public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException { Short value = rs.getShort(names[0]); return value != null ? value.toString() : null; } @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws SQLException { if (value == null) { st.setNull(index, Types.SMALLINT); } else { st.setShort(index, Short.parseShort((String) value)); } } @Override public Object deepCopy(Object value) { return value; } @Override public boolean isMutable() { return false; } @Override public Serializable disassemble(Object value) { return (Serializable) value; } @Override public Object assemble(Serializable cached, Object owner) { return cached; } @Override public Object replace(Object original, Object target, Object owner) { return original; } }
然后在HBM XML中引用这个自定义类型:
<property name="year" type="com.yourpackage.StringToShortType"> <column name="year" sql-type="smallint" /> </property>
方案2:通过额外的Getter/Setter转换
如果不想自定义类型,可以在Java实体类中添加用于转换的Getter/Setter,让Hibernate通过这些方法处理数值类型:
Java实体类:
public class YourEntity { private String year; // 原有的String类型属性方法 public String getYear() { return year; } public void setYear(String year) { this.year = year; } // 供Hibernate使用的转换方法 public Short getYearAsShort() { return year != null ? Short.parseShort(year) : null; } public void setYearAsShort(Short year) { this.year = year != null ? year.toString() : null; } }
HBM XML配置:
<property name="yearAsShort" column="year" type="short" access="property" />
注意:这种方法需要确保业务代码只使用原有的getYear()和setYear()方法,避免直接操作转换后的方法。
内容的提问来源于stack exchange,提问作者dunnofizzbuzz
相关产品推荐
相关产品推荐

