2
votes

SQLSyntaxErrorException: ORA-00932: types de données incohérents: DATE prévue a obtenu BINARY

J'apprécierais de l'aide sur cette exception.

J'ai fait quelques recherches sur cette erreur mais je n'ai pas trouvé de solution. J'utilise JPA avec hibernate et j'obtiens cette erreur lors de l'exécution d'une requête.

De toute évidence, il y a quelque chose que je ne comprends pas à propos de java LocalDate et oracle Date. :(

Voici l'objet:

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

Comme vous pouvez le voir, j'ai essayé d'utiliser des convertisseurs qui convertissent LocalDate en java.util.Date ou java .sql.Date et vice-versa - les deux n'ont malheureusement pas aidé.

Voici la requête:

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

Voici l'exception:

java.sql.SQLSyntaxErrorException: ORA-00932: types de données incohérents: le DATE prévu a obtenu le BINAIRE

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)

Merci beaucoup à l'avance pour toute indication!


5 commentaires

Quelle est la version de votre pilote Oracle JDBC? essayez-en un plus frais!


Malheureusement, je ne pourrai pas le changer car il est indiqué dans l'image docker jboss.


J'ai découvert que je n'avais pas utilisé la dernière version de JPA et je l'ai modifiée. Malheureusement, le problème demeure. J'ai échangé LocalDate & LocalDateTime dans mon application avec java.util.Date, et cela fonctionne. Mais je préférerais vraiment utiliser LocalDate et LocalDateTime.


Essayez quelque chose comme ceci: pensées-on-java.org/persist-localdate- localdatetime-jpa


J'ai trouvé cela aussi et l'ai essayé, malheureusement, sans succès.


4 Réponses :


0
votes

Bien que cela semble contre-intuitif, vous devriez passer une représentation sous forme de chaîne, comme ceci:

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

date_of_birth est de type DATE code > ( MySQL , pas Oracle , mais cela ne devrait pas avoir d'importance) et mappé à LocalDate dans Spring / Hibernation


1 commentaires

Dans Oracle, vous voudrez peut-être utiliser TO_CHAR () / TO_DATE () car il ne coexiste pas bien avec les normes ...



0
votes

Hibernate 4 est sorti avant l'ajout de java.time.LocalDate et il ne le comprend pas. Il envoie donc les données sous forme binaire à Oracle.

La meilleure solution consiste à passer à Hibernate 5.


2 commentaires

Mmh, en fait, j'utilise hibernate-core-5.4.1.Final.jar.


Votre réponse m'a amené à découvrir que je n'utilisais pas JPA 2.2 qui supporte en théorie LocalDate et LocalDateTime. Malheureusement, le problème n'a pas été résolu par ce changement.



0
votes

J'ai découvert que notre image de docker utilise JBoss 6.4, qui - selon https: // access. redhat.com/articles/112673 - utilise Hibernate JPA 2.0 .

Donc, cela ne peut pas fonctionner. Nous avons besoin de JPA 2.2 pour prendre en charge LocalDate et LocalDateTime.

J'ai changé toutes les occurrences de LocalDate et LocalDateTime dans les DAO avec Date, tandis que le reste de mon application continue à utiliser LocalDate et LocalDateTime - avec l'aide d'un petit convertisseur:

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

Théoriquement, il manque une méthode qui convertit Date en LocalDateTime, mais dans mon cas, je n'en ai pas besoin car j'utilise LocalDateTime uniquement pour creationDates qui ne sont jamais lire.


0 commentaires

0
votes

Le problème n'est pas dans le mappage de la sortie mais dans le mappage du paramètre.

Alors que hibernate gère les beans, il sait qu'il doit convertir de LocalDate à Date.

Je ne sais pas pourquoi mais entityManager ne fait pas la même chose pour l'entrée des paramètres. Je suppose que entityManager a une liste plus courte de classes connues avec des convertisseurs et d'autres sont converties en utilisant toString ().

Vous devez convertir votre paramètre d'entrée en Date:

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

Si vous utilisez Spring, vous pouvez également org.springframework.data.jpa.repository.Query

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

Il convertira automatiquement votre paramètre d'entrée.


0 commentaires