【问题标题】:SQLSyntaxErrorException: ORA-00932: inconsistent datatypes: expected DATE got BINARYSQLSyntaxErrorException:ORA-00932:不一致的数据类型:预期 DATE 得到 BINARY
【发布时间】:2019-08-25 23:20:46
【问题描述】:

我将不胜感激有关此异常的一些帮助。

我对此错误进行了一些研究,但找不到解决方案。我将 JPA 与 hibernate 一起使用,并在执行查询时出现此错误。

显然,关于 java LocalDate 和 oracle Date 有一些我不明白的地方。 :(

这是对象:

@Entity
@Table(name = "MY_TABLE")
public class MyObject implements Serializable {

    private static final long serialVersionUID = 1731972128723930612L;

    @Id
    @OneToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OTHER_ID", nullable = false)
    private OtherObject otherObject;

    @Column(name = "MY_DATE", columnDefinition="DATE", nullable = false)
   // @Convert(converter = LocalDateSQLDateConverter.class)
   // @Convert(converter = LocalDateConverter.class)
    private LocalDate date;

如您所见,我尝试使用将 LocalDate 转换为 java.util.Date 或 java.sql.Date 的转换器,反之亦然 - 不幸的是,两者都没有帮助。

这是查询:

public class MyDao extends BaseDao {

    public void save(MyObject object) {
        entityManager.persist(object);
    }

    public MyObject findByDate(LocalDate date) {
        TypedQuery<MyObject> query = entityManager.createQuery("SELECT w from MyObject w"
                + " where w.date = :date", MyOBject.class)
                .setParameter("date", date);
        return query.getResultList().stream().findFirst().orElse(null);
    }

这是个例外:

java.sql.SQLSyntaxErrorException:ORA-00932:不一致的数据类型: 预计 DATE 为 BINARY

oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445) oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450) oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207) oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:884) oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1167) oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1289) oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3584) oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3628) oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1493) org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:462) org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79) org.hibernate.loader.Loader.getResultSet(Loader.java:2090) org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887) org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1866) org.hibernate.loader.Loader.doQuery(Loader.java:905) org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:347) org.hibernate.loader.Loader.doList(Loader.java:2578) org.hibernate.loader.Loader.doList(Loader.java:2564) org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2394) org.hibernate.loader.Loader.list(Loader.java:2389) org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:495) org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:357) org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:198) org.hibernate.internal.SessionImpl.list(SessionImpl.java:1230) org.hibernate.internal.QueryImpl.list(QueryImpl.java:101) org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:268) my.company.path.MyDao.findByDate(MyDaoDao.java:21)

非常感谢任何提示!

【问题讨论】:

  • 您的 Oracle JDBC 驱动程序是什么版本?试试更新鲜的!
  • 不幸的是,我无法更改它,因为它是在 jboss docker 映像中给出的。
  • 我发现我没有使用最新的 JPA 版本并更改了它。不幸的是,问题仍然存在。我在我的应用程序中用 java.util.Date 交换了 LocalDate 和 LocalDateTime,这很有效。但我真的更喜欢使用 LocalDate 和 LocalDateTime。
  • 我也发现了,试了一下,可惜没有成功。

标签: java oracle hibernate jpa


【解决方案1】:

虽然看起来有悖常理,但您应该传递一个字符串表示形式,如下所示:

SELECT * FROM xxx where date_of_birth = '1990-08-21';

其中date_of_birthDATE 类型(MySQL,不是Oracle,但应该没关系)并映射到Spring 中的LocalDate@/Hibernate

【讨论】:

  • 在 Oracle 中,您可能希望使用 TO_CHAR()/TO_DATE(),因为它不能与标准很好地共存...
【解决方案2】:

Hibernate 4 在添加 java.time.LocalDate 之前就出来了,它不理解它。因此,它将数据以二进制形式发送到 Oracle。

最好的解决办法是升级到 Hibernate 5。

【讨论】:

  • 嗯,其实我用的是hibernate-core-5.4.1.Final.jar。
  • 您的回答让我发现我没有使用理论上支持 LocalDate 和 LocalDateTime 的 JPA 2.2。不幸的是,此更改并未解决问题。
【解决方案3】:

我发现我们的 docker 映像使用 JBoss 6.4,根据 https://access.redhat.com/articles/112673,它使用 Hibernate JPA 2.0

所以,这行不通。我们需要 JPA 2.2 来支持 LocalDate 和 LocalDateTime。

我用 Date 更改了 DAO 中所有出现的 LocalDate 和 LocalDateTime,而我的应用程序的其余部分继续使用 LocalDate 和 LocalDateTime - 在一个小转换器的帮助下:

public class LocalDateConverter {

    public static Date convertToDate(LocalDate date) {
        return date != null ? Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()) : null;
    }

    public static LocalDate convertToLocalDate(Date date) {
        return date != null ? LocalDate.from(date.toInstant().atZone(ZoneId.systemDefault())) : null;
    }

    public static Date convertToDate(LocalDateTime dateTime) {
        return dateTime != null ? Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant()) : null;
    }
}

理论上,缺少一种将 Date 转换为 LocalDateTime 的方法,但在我的情况下,我不需要它,因为我只将 LocalDateTime 用于从不读取的 creationDates。

【讨论】:

    【解决方案4】:

    问题不在于输出的映射,而在于参数的映射。

    当 hibernate 管理 bean 时,它知道它必须从 LocalDate 转换为 Date。

    我不知道为什么,但是 entityManager 对参数输入没有做同样的事情。我假设 entityManager 有一个较短的已知类与转换器的列表,而其他类则使用 toString() 进行转换。

    您必须将输入参数转换为日期:

    TypedQuery<MyObject> query = entityManager.createQuery("SELECT w from MyObject w"
                + " where w.date = :date", MyOBject.class)
                .setParameter("date",Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
    

    如果你使用Spring,你还可以使用org.springframework.data.jpa.repository.Query

     @Query("SELECT w from MyObject w where w.date = :date")
     public MyObject findByDate(LocalDate date);
    

    它会自动转换你的输入参数。

    【讨论】:

      猜你喜欢
      • 2013-05-11
      • 2014-06-06
      • 2018-10-30
      • 2019-05-04
      • 2017-12-28
      • 1970-01-01
      • 2017-04-21
      • 2017-10-29
      • 2013-05-31
      相关资源
      最近更新 更多