通过java.util.Date

时间:2019-01-28 15:03:12

标签: spring oracle hibernate jpa

我目前正在将Spring Boot应用程序从MariaDB迁移到OracleDB。 Spring / Java后端使用Hibernate / JPA生成针对MariaDB数据库的查询,因此从理论上讲,迁移应该相当轻松。更改方言即可完成。实际上,事实证明,在将类型绑定到数据库类型时,OracleDB 12C的休眠方言做出了一些奇怪的假设。后端在其所有日期中仍然使用旧的java.util.Date类型,Hibernate似乎希望将其强制转换为Long(据我所知甚至更过时)或某种BLOB类型。 BLOB当然很棒,但是将Date映射到DATE似乎更直观。 因为该行当前设置为期望DATE,所以每次尝试访问该行时都会出现以下错误:

InvalidDataAccessResourceUsageException: could not extract ResultSet
ORA-00932: inconsistent datatypes: expected - got BLOB

我尝试使用JPA Converter功能将这些Date对象手动转换为Hibernate不会弄乱的东西,但这导致Hibernate期望使用VARBINARY,如本文所述: https://dzone.com/articles/leaky-abstractions-or-how-bind

@Converter(autoApply = false)
public class DateDATEAttributeConverter implements AttributeConverter<Date, DATE> {

    @Override
    public DATE convertToDatabaseColumn(Date date){
        return new DATE(); // conversion to be done later
    }

    @Override
    public Date convertToEntityAttribute(DATE date) {
        return new Date(); // conversion to be done later
    }

}

使用这个非常小的转换器,并在调试器中逐步运行代码,这表明一切似乎都正确地附加到了preparedstatement,但是随后被Hibernate拒绝,并带有一个     org.hibernate.exception.SQLGrammarException:无法提取ResultSet 错误。

此后,我决定尝试像上面的文章中那样创建客户UserType,并在此处进行详细说明: https://www.baeldung.com/hibernate-custom-types

我目前通过使用此自定义类型将java.util.Date转换为Oracle DATE。 @Type批注用于确保使用此CustomType实现转换相关字段。可悲的是,在实现所有这些之后,与以前相同的错误返回。似乎在幕后某个地方,仍然存在着转换/绑定,我没有设法影响。

@Override
public Object nullSafeGet(
        ResultSet rs,
        String[] names,
        SessionImplementor session,
        Object owner
)
        throws SQLException {
    LOGGER.debug("nullSafeGet: " + names[0]);
    return rs.getTimestamp(names[0]);
}

@Override
public void nullSafeSet(
        PreparedStatement st,
        Object value,
        int index,
        SessionImplementor session
)
        throws SQLException {
    if(Objects.isNull(value)){
        st.setNull(index, Types.DATE);
    }else{
        Date dateUtil = (Date)value;
        LocalDate localDate = dateUtil.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
        java.sql.Date dateSQL = java.sql.Date.valueOf(localDate);
        DATE date = new DATE(dateSQL);
        LOGGER.debug("nullSafeSet: " + date);
        st.setObject(index, date);
    }

}

有没有建立好的方法来解决这个问题?我已经在网上进行了很多搜索,但是除了这两篇文章之外,我没有得到更多的收获,或者被告知停止使用诸如Date之类的旧类型。可悲的是,对于大型的旧项目和新的截止日期,这不是一个可取的选择。

0 个答案:

没有答案