2
votes

Spring Data JDBC: DataRetrievalFailureException: impossible de convertir [oracle.sql.ROWID] en [java.lang.Number]

Je suis nouveau sur Spring Data JDBC, et j'ai du mal à créer un Dto simple et à le faire persister sur la base de données.

J'utilise Spring-Boot 2.1.1.RELEASE et Oracle 12 Database. p>

UserDto

org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
        at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:79) ~[spring-jdbc-5.1.3.RELEASE.jar:5.1.3.RELEASE]
        at org.springframework.data.jdbc.core.DefaultDataAccessStrategy.getIdFromHolder(DefaultDataAccessStrategy.java:323) ~[spring-data-jdbc-1.0.3.RELEASE.jar:1.0.3.RELEASE]

UserDao

public String createUser() {
    UserDto userDto = new UserDto().setUserName("mapss@sapot.wrong.email.pt").setPassword("superpass").setUserType("Guest").setActive(true);
    logger.info(String.format("Creating user: " + userDto));

    userDto.setNew(true);
    UserDto persistedUser = userDao.save(userDto);

    logger.info(String.format("Persisted user: " + persistedUser));
    return "Ending of create user operation";
}

et j'essaie simplement de le conserver sur la base de données comme ceci

@Repository
public interface UserDao extends CrudRepository<UserDto, String> {

    @Query("SELECT * FROM USERS_T u WHERE u.USR_USERNAME = :userName")
    UserDto findByUserName(@Param("userName") String userName);
}

Je reçois cette exception.

@Table(value="USERS_T")
public class UserDto extends PersistableDto {
    @Id
    @Column(value="USR_USERNAME")
    private String userName;

    @Column(value="USR_FIRSTNAME")
    private String firstName;

    @Column(value="USR_LASTNAME")
    private String lastName; 
.....
}

Je crois que cela est en quelque sorte lié au fait que @Id est une chaîne.

Quelqu'un peut-il m'aider à comprendre ce que je fais de mal? Pourquoi ce comportement. Sur les spécifications, je ne vois pas et restriction au type de l'Id. S'agit-il d'un problème d'intégration d'Oracle? Comment puis-je résoudre ce problème?

Merci à tous pour votre aide.


5 commentaires

J'ai essayé d'ajouter un identifiant de type Long, le problème persiste. Cela signifie que l'exception n'a rien à voir avec le type @Id mais probablement un problème entre SpringData et Oracle Database


J'ai remarqué que sur la base de données, les enregistrements de cette table ont le ROWID suivant: 'AACVejAAJAAAAFOAAA', 'AACVejAAJAAAAFOAAB', 'AACVejAAJAAAAFOAAC' Bug le GeneratedKeyHolder qui implémente KeyHolder attend que la clé soit un nombre. docs.spring.io/ spring / docs / current / javadoc-api / org /… Qu'est-ce que cela signifie? Y a-t-il une incompatibilité entre Spring et Oracle 12?


Il semble que vous n'ayez pas défini de primaire numérique dans votre tableau. Définissez une clé primaire, dites Id du numéro de type dans votre table, puis mettez à jour votre classe d'entité. Comme vous n'avez pas de clé primaire, oracle utilise peut-être le ROWID


En fait, j'ai fait: CREATE TABLE USERS_T (USR_ID NUMBER (19) DEFAULT USERS_ID_SEQ.nextval NOT NULL, ......., CONSTRAINT USERS_T_PK PRIMARY KEY (USR_ID));


La version du pilote oracle que j'utilise est: ojdbc8 18.3.0.0.0. Finalement, cela peut être lié.


3 Réponses :


0
votes

Je pense que vous devez déclarer le champ USR_ID et la séquence correspondante dans votre entité

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "XXXX")
@SequenceGenerator(sequenceName = "YYYY", allocationSize = 1, name = "XXXX")
Long USR_ID;


2 commentaires

La question concerne Spring Data JDBC et non JPA.


Suis-je le premier à essayer d'utiliser Spring Data JDBC avec une base de données Oracle? Je commence à avoir une impression que oui.



2
votes

Malheureusement, Oracle n'est pas encore entièrement pris en charge. Il existe un problème ouvert pour la création de tests d'intégration pour Oracle et le accompagnateur PR corrige déjà certains problèmes, mais certainement pas tous.

Le principal problème ici est qu'Oracle fait des choses intéressantes concernant la génération de clés générées. Je vois les options suivantes

a) N'utilisez pas la génération de clé côté base de données. DATAJDBC-282 rend cela plus confortable. Mais ce n'est pour l'instant que dans la version SNAPSHOT.

b) N'utilisez pas Oracle. Nous testons actuellement avec MySql, Postgres, H2, HSQLDB et MariaDb

c) Jetez un œil au PR mentionné ci-dessus pour voir si vous pouvez le corriger suffisamment pour qu'il fonctionne.

Je suis conscient que ces options ne sont pas très satisfaisantes. Le défi est qu'il est vraiment difficile pour un projet Open Source de faire des tests d'intégration avec Oracle, car même télécharger un pilote Oracle JDBC légal à partir d'une version publique de CI est un cauchemar, sans parler d'une base de données.

Un collègue m'a envoyé cette image lorsque nous discutions de la situation:

 entrez la description de l'image ici

Mais nous n'abandonnons pas, un support approprié sera ajouté.


0 commentaires

1
votes

J'ai souffert du même problème, alors que le PR est inclus dans la prochaine version de Spring Data JDBC, nous pouvons utiliser la solution de contournement suivante avec Spring AOP, ce n'est pas "parfait" mais suffisant pour nous jusqu'à ce que le problème sous-jacent soit résolu:

@Around("execution(public * my-app-pacakage.repository.*.save(..))")
public Object aspectController(ProceedingJoinPoint jp) throws Throwable {
    try {
        return jp.proceed();
    } catch (DbActionExecutionException e) {
        if (e.getCause() instanceof DataRetrievalFailureException) {
            return jp.getArgs()[0];
        }
        return e;
    } catch(Throwable e) {
        throw e;        
    }       
}


0 commentaires