Jdbi: Error de métodos ambiguos (método de puente faltante) para la sobrecarga covariante de Kotlin

Creado en 9 ago. 2019  ·  8Comentarios  ·  Fuente: jdbi/jdbi

EDITAR: actualizado con un ejemplo más simple.

De acuerdo con la documentación, los genéricos y JDBI funcionan juntos, y he visto esto funcionar antes (aunque con una versión anterior de JDBI), pero por alguna razón ahora aparece un error:

org.jdbi.v3.sqlobject.UnableToCreateSqlObjectException: la barra de interfaz tiene métodos ambiguos [resumen público java.lang.Object Foo.baz (java.util.UUID), resumen público java.util.UUID Bar.baz (java.util.UUID )], resuelva con una anulación explícita

http://jdbi.org/#_annotations_and_inheritance

Probé @Override por si

interface Foo<T> {
    <strong i="12">@SqlQuery</strong>
    fun baz(a: UUID): T
}

interface Bar : Foo<UUID> {
    @SqlQuery("SELECT ClientID " +
              "FROM ClientInstance " +
              "WHERE ClientInstanceID = ?")
    override fun baz(a: UUID): UUID
}

JDBI.inTransactionUnchecked { handle ->
    val tester = handle.attach(Bar::class.java)
    val hest = tester.baz(UUID.fromString("7a949c0e-28db-424a-a449-b118e5175a3b"))
    LOGGER.info { "hest $hest" }
}
bug

Comentario más útil

Hola Tor,
Probamos que una construcción muy similar funciona en Java vainilla: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Quizás perdimos un caso para Kotlin. Deberíamos agregar una prueba correspondiente a su uso aquí y corregir cualquier error que se descubra.

Todos 8 comentarios

Hola Tor,
Probamos que una construcción muy similar funciona en Java vainilla: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Quizás perdimos un caso para Kotlin. Deberíamos agregar una prueba correspondiente a su uso aquí y corregir cualquier error que se descubra.

Ah, mirando más de cerca: tenga en cuenta que los tipos de devolución son diferentes, Object vs UUID . Supongo que esto significa que el compilador de Kotlin está emitiendo un método de puente sintético que luego no estamos manejando correctamente.

Para las personas que buscan en Google, este error produce un mensaje de error diferente cuando la interfaz principal no está anotada (¡me tomó un tiempo encontrar esto!)

Exception in thread "main" java.lang.IllegalStateException: Method StringRepo.get must be default or be annotated with a SQL method annotation.
    at org.jdbi.v3.sqlobject.SqlObjectFactory.lambda$buildMethodHandler$15(SqlObjectFactory.java:148)
...
interface Repo<T> {
    fun get(): T
}
interface StringRepo : Repo<String> {
    @SqlQuery("SELECT 'Hello world!'")
    override fun get(): String
}
//...snip
jdbi.onDemand(StringRepo::class.java).get()

@LittleMikeDev , ese es un problema ligeramente diferente. He mejorado los mensajes de error para que no sean engañosos sobre la clase a la que le falta la anotación: https://github.com/jdbi/jdbi/pull/1590/files#diff -75b1c04d402bd8924262c7fececfcdb1L166

Como solución alternativa, Jdbi podría emular el método puente necesario. El código necesario probablemente termine siendo pequeño pero muy complicado de escribir. Espero que Kotlin al menos evalúe el problema pronto.

@stevenschlansker Gracias por investigarlo.
Kotlin debe haber tenido este puente antes porque lo he visto funcionar. - Esto explica por qué no pude volver a hacerlo funcionar volviendo a versiones anteriores de JDBI.

Parece que esto fue un compromiso para mantener la compatibilidad con Java 6: 6 no admitía métodos de puente en las interfaces, por lo que Kotlin no los emite. Eso suena muy tonto hoy en día, pero probablemente tenía sentido hace 10 años;) Con suerte, dejarán de admitir 6 pronto, o al menos permitirán la compatibilidad condicionalmente con el mundo post-6.

¿Fue útil esta página
0 / 5 - 0 calificaciones