【问题标题】:Wrong column type encountered with User-Defined Data Type使用用户定义的数据类型遇到错误的列类型
【发布时间】:2017-01-24 10:04:36
【问题描述】:

我正在使用休眠从 SQL Server 2014 数据库中获取一些数据。

有一个包含用户定义数据类型列的表:

dbo.Nodos
    Id (PK, int, not null)
    Tipo (PK, FK, TipoNodo(tinyint), not null)
    Nombre (varchar(40), null)
    PosX (Coordenada(real), not null)
    PosY (Coordenada(real), not null)
    Label (varchar(8), not null)

这些数据类型是 Coordenada 和 TipoNodo:

User-Defined Data Types
    dbo.Coordenada (real, not null)
    dbo.TipoNodo (tinyint, not null)

我在 Java 中将 Nodos 表映射为 StopDTO 类:

@Entity
@Table(name = "Nodos")
public class StopDTO {

    /*
     * Atributos
     */
    @Id
    @Column(name = "Id", insertable = false, updatable = false)
    private Integer id;
    @Column(name = "Tipo", insertable = false, updatable = false)
    private Integer tipo;
    @Column(name = "Nombre", insertable = false, updatable = false)
    private String nombre;
    @Column(name = "PosX", insertable = false, updatable = false)
    private Float posx;
    @Column(name = "PosY", insertable = false, updatable = false)
    private Float posy;
    @Column(name = "Label", insertable = false, updatable = false)
    private String label;
    ...

当我查询 StopDTO(使用 NamedNativeQuery)时出现问题,我收到以下消息:

引起:org.hibernate.tool.schema.spi.SchemaManagementException: 架构验证:在 [PosX] 列中遇到错误的列类型 表[节点];找到 [coordenada (Types#REAL)],但期待 [float (类型#FLOAT)] 在 org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateColumnType(SchemaValidatorImpl.java:165) 在 org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateTable(SchemaValidatorImpl.java:150) 在 org.hibernate.tool.schema.internal.SchemaValidatorImpl.performValidation(SchemaValidatorImpl.java:95) 在 org.hibernate.tool.schema.internal.SchemaValidatorImpl.doValidation(SchemaValidatorImpl.java:62) ...

是否通过为 Coordenada 和 TipoNodo 实现几个 UserTypes 解决了这个问题?如果不是,我该怎么办?

谢谢!

【问题讨论】:

    标签: java hibernate sql-server-2014


    【解决方案1】:

    请检查Hibernate中配置的方言,应该是SQLServer2008Dialect。

    【讨论】:

    • 我有:configuration.setProperty(AvailableSettings.DIALECT, "org.hibernate.dialect.SQLServer2012Dialect");
    【解决方案2】:

    解决了!

    果然不出所料:开发了一对UserType。如果有人需要,我会发布代码:

    TipoNodoUserType

    package com.mycompany.usertype;
    import java.io.Serializable;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    import java.util.Objects;
    
    import org.hibernate.HibernateException;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.type.descriptor.java.ShortTypeDescriptor;
    import org.hibernate.usertype.UserType;
    
    public class TipoNodoUserType implements UserType {
    
        public static final TipoNodoUserType INSTANCE = new TipoNodoUserType();
    
        @Override
        public int[] sqlTypes() {
            return new int[] {Types.TINYINT};
        }
    
        @SuppressWarnings("rawtypes")
        @Override
        public Class returnedClass() {
            return Short.class;
        }
    
        @Override
        public boolean equals(Object x, Object y) throws HibernateException {
            return Objects.equals(x, y);
        }
    
        @Override
        public int hashCode(Object x) throws HibernateException {
            return Objects.hashCode(x);
        }
    
        @Override
        public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
                throws HibernateException, SQLException {
            String columnName = names[0];
            Short columnValue = (Short) rs.getObject(columnName);
            return columnValue == null ? null : columnValue;
        }
    
        @Override
        public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
                throws HibernateException, SQLException {
            if(value == null){
                st.setNull( index, Types.TINYINT );
            }else{
                String stringValue = ShortTypeDescriptor.INSTANCE.toString((Short)value);
                st.setString(index, stringValue);
            }
        }
    
        @Override
        public Object deepCopy(Object value) throws HibernateException {
            return value;
        }
    
        @Override
        public boolean isMutable() {
            return true;
        }
    
        @Override
        public Serializable disassemble(Object value) throws HibernateException {
            return (Serializable) value;
        }
    
        @Override
        public Object assemble(Serializable cached, Object owner) throws HibernateException {
            return cached;
        }
    
        @Override
        public Object replace(Object original, Object target, Object owner) throws HibernateException {
            return original;
        }
    
    }
    

    坐标用户类型

    package com.mycompany.usertype;
    import java.io.Serializable;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    import java.util.Objects;
    
    import org.hibernate.HibernateException;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.type.descriptor.java.FloatTypeDescriptor;
    import org.hibernate.usertype.UserType;
    
    public class CoordenadaUserType implements UserType {
    
        public static final CoordenadaUserType INSTANCE = new CoordenadaUserType();
    
        @Override
        public int[] sqlTypes() {
            return new int[] {Types.REAL};
        }
    
        @SuppressWarnings("rawtypes")
        @Override
        public Class returnedClass() {
            return Float.class;
        }
    
        @Override
        public boolean equals(Object x, Object y) throws HibernateException {
            return Objects.equals(x, y);
        }
    
        @Override
        public int hashCode(Object x) throws HibernateException {
            return Objects.hashCode(x);
        }
    
        @Override
        public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor session, Object owner)
                throws HibernateException, SQLException {
            String columnName = names[0];
            Float columnValue = (Float) rs.getObject(columnName);
            return columnValue == null ? null : columnValue;
        }
    
        @Override
        public void nullSafeSet(PreparedStatement st, Object value, int index, SessionImplementor session)
                throws HibernateException, SQLException {
            if(value == null){
                st.setNull( index, Types.REAL );
            }else{
                String stringValue = FloatTypeDescriptor.INSTANCE.toString((Float)value);
                st.setString(index, stringValue);
            }
        }
    
        @Override
        public Object deepCopy(Object value) throws HibernateException {
            return value;
        }
    
        @Override
        public boolean isMutable() {
            return true;
        }
    
        @Override
        public Serializable disassemble(Object value) throws HibernateException {
            return (Serializable) value;
        }
    
        @Override
        public Object assemble(Serializable cached, Object owner) throws HibernateException {
            return cached;
        }
    
        @Override
        public Object replace(Object original, Object target, Object owner) throws HibernateException {
            return original;
        }
    
    }
    

    StopDTO

        @Entity
    @Table(name = "Nodos")
    public class StopDTO implements java.io.Serializable{
    
        /*
         * Atributos
         */
        private static final long serialVersionUID = 8171715812406080593L;
    
        @Id
        @Column(name = "Id", insertable = false, updatable = false)
        private Integer id;
        @Id
        @Column(name = "Tipo", insertable = false, updatable = false)
        @Type(type = "com.mycompany.usertype.TipoNodoUserType")
        private Short tipo;
        @Column(name = "Nombre", insertable = false, updatable = false)
        private String nombre;
        @Column(name = "PosX", insertable = false, updatable = false)
        @Type(type = "com.mycompany.usertype.CoordenadaUserType")
        private Float posx;
        @Column(name = "PosY", insertable = false, updatable = false)
        @Type(type = "com.mycompany.usertype.CoordenadaUserType")
        private Float posy;
        @Column(name = "Label", insertable = false, updatable = false)
        private String label;
        ...
        // Don't forget to code an empty constructor, setters/getters for every attribute and implementing hashCode and equals methods (as we're implementing Serializable interface).
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-25
      • 1970-01-01
      • 1970-01-01
      • 2014-01-19
      • 1970-01-01
      • 2020-11-19
      • 1970-01-01
      相关资源
      最近更新 更多