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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:55:35