SQLSyntaxErrorException:ORA-00932:数据类型不一致:预期日期为BINARY

时间:2019-04-04 09:05:11

标签: java oracle hibernate jpa

希望您能对此例外有所帮助。

我对此错误进行了一些研究,但找不到解决方案。我在休眠状态下使用JPA并在执行查询时收到此错误。

很显然,关于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)

非常感谢您提供任何提示!

4 个答案:

答案 0 :(得分:0)

虽然看起来很直观,但您应该传递一个字符串表示形式,如下所示:

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

其中date_of_birth的类型为DATEMySQL,而不是Oracle,但没有关系)并映射到{{1}中的LocalDate } / Spring

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

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

因此,这是行不通的。我们需要 JPA 2.2 以支持LocalDate和LocalDateTime。

我用日期更改了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用于从未读取的creationDate。

答案 3 :(得分:0)

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

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

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

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

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);
     

它将自动转换您的输入参数。