2016-11-21 102 views
0

我是一位不幸的开发人员,需要使用非常遗留的数据库。问题是,该数据库包含自定义数据类型:Hibernate JPA DB2自定义数据类型

CREATE DISTINCT TYPE SCHEMA.T_STUPID_ID AS 
    SMALLINT WITH COMPARISONS 
; 

所以我不能改变的,但需要得到的数据和查询。

DB2 SQL Error: SQLCODE=-401, SQLSTATE=42818, SQLERRMC==, DRIVER=4.19.26 

是:一个操作的操作数的数据类型并不看来,这是行不通的,使用弹簧数据JPA(资料库),我收到以下错误引起的ID(findOne)查询时兼容 所以它听起来像查询不使用自定义类型的工作:/

我也试过这样:

@Query("select p from ImSickOfThisEntity p where cast(p.entityId as integer) 
= ?1 ") 

但我得到:

DB2 SQL Error: SQLCODE=-461, SQLSTATE=42846, SQLERRMC=IPSDBO.T_PRODUCT_ID;SYSIBM.INTEGER 

翻译为:

A VALUE WITH DATA TYPE source-data-type CANNOT BE CAST TO TYPE target-data-type 

如何处理这样的自定义类型?谷歌没有帮助,我只能找到具有标准数据库列类型的自定义Java类型....

回答

0

您需要实现一个UserType,并且您可以指定sqlTypes。

public class SmallIntHibernateType implements UserType { 

@Override 
public int[] sqlTypes() { 
    return new int[] {Types.SMALLINT}; 
} 

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

@Override 
public boolean equals(Object o, Object o2) throws HibernateException { 
    if (o == null && o2 == null) { 
     return true; 
    } else if (o == null) { 
     return false; 
    } else if (o2 == null) { 
     return false; 
    } else { 
     return ((Integer) o).intValue() == ((Integer) o2).intValue(); 
    } 
} 

@Override 
public int hashCode(Object o) throws HibernateException { 
    return o.hashCode(); 
} 

@Override 
public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sessionImplementor, Object o) throws HibernateException, SQLException { 
    return resultSet.getInt(strings[0]); 
} 

@Override 
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SharedSessionContractImplementor sessionImplementor) throws HibernateException, SQLException { 
    if (value == null || value.equals(0)) { 
     preparedStatement.setNull(index, Types.INTEGER); 
     return; 
    } 

    if (!(value instanceof Integer)) { 
     throw new UnsupportedOperationException("can't convert " + value.getClass()); 
    } 

    preparedStatement.setInt(index, ((Integer) value)); 
} 

@Override 
public Object deepCopy(Object value) throws HibernateException { 
    if (value == null) { 
     return null; 
    } 

    if (!(value instanceof Integer)) { 
     throw new UnsupportedOperationException("can't convert " + value.getClass()); 
    } 

    return value; 
} 

@Override 
public boolean isMutable() { 
    return false; 
} 

@Override 
public Serializable disassemble(Object value) throws HibernateException { 
    if (!(value instanceof Integer)) { 
     throw new UnsupportedOperationException("can't convert " + value.getClass()); 
    } 

    return (Integer) value; 
} 

@Override 
public Object assemble(Serializable cached, Object owner) throws HibernateException { 
    if (!(cached instanceof Integer)) { 
     throw new UnsupportedOperationException("can't convert " + cached.getClass()); 
    } 

    return cached; 
} 

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

然后在你的实体上,你需要指定使用的类型。

@Id 
@Type(type = "com.data.system.SmallIntHibernateType") 
private int id; 
+0

因此,如果我使用@Type注释,SmallIntHibernateType的目的是什么?它是spring-data-jpa存储库中的where子句参数吗? – maslan

+0

SmallIntHybernateType类实际上是告诉hibernate该列是什么SQL类型并将其转换为Java类型的工作。 @Type注释是hibernate查找自定义列类型的要点。 – Mamof

+0

好吧,那没用,即使没有这个,数据检索也没有问题。查询存在问题 - where子句不起作用,因为DB2声明它是一种错误的类型。我使用的唯一解决方案是在SpringDataJPA存储库中使用强制转换的本地查询 – maslan