Jdbi: Mehrdeutiger Methodenfehler (fehlende Brückenmethode) für kovariante Überladung von Kotlin

Erstellt am 9. Aug. 2019  ·  8Kommentare  ·  Quelle: jdbi/jdbi

EDIT: Aktualisiert mit einem einfacheren Beispiel.

Laut der Dokumentation arbeiten Generika und JDBI zusammen, und ich habe diese Arbeit schon einmal gesehen (wenn auch mit einer älteren Version von JDBI), aber aus irgendeinem Grund bekomme ich jetzt eine Fehlermeldung:

org.jdbi.v3.sqlobject.UnableToCreateSqlObjectException: Interface Bar hat mehrdeutige Methoden [öffentliche Zusammenfassung java.lang.Object Foo.baz(java.util.UUID), öffentliche Zusammenfassung java.util.UUID Bar.baz(java.util.UUID )], bitte mit einer expliziten Überschreibung auflösen

http://jdbi.org/#_annotations_and_inheritance

Ich habe @Override ausprobiert, aber das hat nichts geändert.

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

Hilfreichster Kommentar

Hallo Tor,
Wir haben getestet, dass eine sehr ähnliche Konstruktion in Vanilla Java funktioniert: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Vielleicht haben wir einen Fall für Kotlin übersehen. Wir sollten hier einen Test hinzufügen, der Ihrer Verwendung entspricht, und jeden aufgedeckten Fehler beheben.

Alle 8 Kommentare

Hallo Tor,
Wir haben getestet, dass eine sehr ähnliche Konstruktion in Vanilla Java funktioniert: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Vielleicht haben wir einen Fall für Kotlin übersehen. Wir sollten hier einen Test hinzufügen, der Ihrer Verwendung entspricht, und jeden aufgedeckten Fehler beheben.

Ah, genauer hinsehen: Beachten Sie, dass die Rückgabetypen unterschiedlich sind, Object vs UUID . Ich gehe davon aus, dass dies bedeutet, dass der Kotlin-Compiler eine synthetische Bridge-Methode ausgibt, die wir dann nicht richtig verarbeiten.

Für Leute, die bei Google suchen, führt dieser Fehler zu einer anderen Fehlermeldung, wenn die übergeordnete Benutzeroberfläche nicht mit Anmerkungen versehen ist (ich habe eine Weile gebraucht, um dies zu finden!)

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 , das ist ein etwas anderes Problem. Ich habe die Fehlermeldung verbessert, um nicht irreführend über die Klasse zu sein, der die Anmerkung fehlt: https://github.com/jdbi/jdbi/pull/1590/files#diff -75b1c04d402bd8924262c7fececfcdb1L166

@TorRanfelt , ich Problem zu beheben. Es sieht so aus, als ob der Kotlin-Compiler keine Bridge-Methode für die kovariante Methodenspezialisierung ausgibt. Ich habe ein Problem mit dem Kotlin-Bugtracker eingereicht: https://youtrack.jetbrains.com/issue/KT-33634

Als Workaround könnte Jdbi die benötigte Bridge-Methode emulieren. Der benötigte Code ist wahrscheinlich klein, aber sehr schwierig zu schreiben. Ich hoffe, Kotlin wird das Problem zumindest bald bewerten.

@stevenschlansker Danke fürs
Kotlin muss diese Brücke schon einmal gehabt haben, denn ich habe gesehen, wie sie funktioniert. - Dies erklärt, warum ich es nicht wieder zum Laufen bringen konnte, indem ich zu älteren Versionen von JDBI zurückkehrte.

Es sieht so aus, als ob dies ein Kompromiss war, um die Kompatibilität mit Java 6 aufrechtzuerhalten: 6 unterstützte keine Bridge-Methoden in Schnittstellen, daher gibt Kotlin sie nicht aus. Das klingt heutzutage mächtig albern, machte aber vor 10 Jahren wahrscheinlich Sinn ;) Hoffentlich wird die 6-Unterstützung bald eingestellt oder zumindest bedingt die Kompatibilität mit der Post-6-Welt ermöglicht.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen