4 votes

Spark JDBC : DataFrameReader ne parvient pas à lire une table Oracle dont le type de données est ROWID

J'essaie de lire une table Oracle en utilisant spark.read.format et cela fonctionne très bien pour toutes les tables sauf quelques tables qui ont une colonne dont le type de données est ROWID.

Voici mon code

var df = spark.read.format("jdbc").
        option("url", url).
        option("driver", driver).
        option("dbtable", dbTable).load()
println(df.first)

Je reçois l'erreur suivante

18/09/08 11:38:17 WARN scheduler.TaskSetManager: Lost task 0.0 in stage 5.0 (TID 23, gbrdsr000002985.intranet.barcapint.com, executor 21): java.sql.SQLException: Invalid column type: getLong not implemented for class oracle.jdbc.driver.T4CRowidAccessor
    at oracle.jdbc.driver.GeneratedAccessor.getLong(GeneratedAccessor.java:440)
    at oracle.jdbc.driver.GeneratedStatement.getLong(GeneratedStatement.java:228)
    at oracle.jdbc.driver.GeneratedScrollableResultSet.getLong(GeneratedScrollableResultSet.java:620)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$org$apache$spark$sql$execution$datasources$jdbc$JdbcUtils$$makeGetter$8.apply(JdbcUtils.scala:365)
    at org.apache.spark.sql.execution.datasources.jdbc.JdbcUtils$$anonfun$org$apache$spark$sql$execution$datasources$jdbc$JdbcUtils$$makeGetter$8.apply(JdbcUtils.scala:364)

Analyse : J'ai vérifié JdbcUtils et a constaté que le cas java.sql.Types.ROWID est mappé avec LongType de spark. Mais getLong n'est pas implémenté pour le type ROWID dans le pilote Oracle JDBC. Je suis persuadé que si je parviens à le faire correspondre à StringType, cela fonctionnera, mais je n'ai pas trouvé de solution à ce problème. Merci de me suggérer une solution.

Pour l'instant, je lis les données à l'aide de ResultSet et je les convertis ensuite en DataFrame à l'aide d'un schéma personnalisé, mais cela tue le parallélisme. Je voulais également vérifier s'il était possible de modifier le code de JdbcUtils car je ne suis pas en mesure d'étendre DataFrameReader pour en créer un personnalisé puisque "private[sql]" est mentionné dans la définition de la classe.

2voto

Maverick Points 11
val df=spark.read
  .format("jdbc")
  .option("driver","oracle.jdbc.OracleDriver")
  .option("url","jdbc:oracle:thin:@localhost:1521:orcl")
  .option("user","oracle1")
  .option("password","oracle1")
  .option("dbtable","(select Cast(RID as VARCHAR2(18)) from sample.ALL_RESULTS_DATA)  my_table")
  .load()

RID est un nom de colonne de type ROWID dans Oracle.

Le code ci-dessus convertit le type de données ROWID en String afin que nous puissions le lire avec Spark.

RÉSULTAT :

-------------------------+
|CAST(RIDASVARCHAR2(18))AS|
+-------------------------+
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|
|       AAAIVuAABAAAMhCAAA|

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X