Jdbi: Ошибка неоднозначных методов (отсутствует метод моста) для ковариантной перегрузки Kotlin

Созданный на 9 авг. 2019  ·  8Комментарии  ·  Источник: jdbi/jdbi

РЕДАКТИРОВАТЬ: обновлен более простым примером.

Согласно документации, дженерики и JDBI работают вместе, и я видел эту работу раньше (хотя и со старой версией JDBI), но по какой-то причине теперь я получаю сообщение об ошибке:

org.jdbi.v3.sqlobject.UnableToCreateSqlObjectException: интерфейс Bar имеет неоднозначные методы [общедоступный абстрактный java.lang.Object Foo.baz (java.util.UUID), общедоступный абстрактный java.util.UUID Bar.baz (java.util.UUID )], разрешите явное переопределение

http://jdbi.org/#_annotations_and_inheritance

Я попробовал @Override для хорошей меры, но это ничего не изменило.

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

Самый полезный комментарий

Привет Тор,
Мы проверили, что очень похожая конструкция работает в ванильной Java: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Возможно, мы упустили случай с Котлином. Мы должны добавить сюда тест, соответствующий вашему использованию, и исправить любую обнаруженную ошибку.

Все 8 Комментарий

Привет Тор,
Мы проверили, что очень похожая конструкция работает в ванильной Java: https://github.com/jdbi/jdbi/blob/master/sqlobject/src/test/java/org/jdbi/v3/sqlobject/TestSqlObject.java#L293 - L307
Возможно, мы упустили случай с Котлином. Мы должны добавить сюда тест, соответствующий вашему использованию, и исправить любую обнаруженную ошибку.

А, если присмотреться: обратите внимание, что типы возвращаемых значений разные: Object vs UUID . Я ожидаю, что это означает, что компилятор Kotlin испускает метод синтетического моста, который мы затем обрабатываем неправильно.

Для людей, выполняющих поиск в Google, эта ошибка выдает другое сообщение об ошибке, когда родительский интерфейс не аннотирован (мне потребовалось время, чтобы найти это!)

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 , это немного другая проблема. Я улучшил сообщение об ошибках, чтобы не вводить в заблуждение относительно класса, в котором отсутствует аннотация: https://github.com/jdbi/jdbi/pull/1590/files#diff -75b1c04d402bd8924262c7fececfcdb1L166

@TorRanfelt , я немного неясно , что делать, чтобы это исправить. Похоже, что компилятор Kotlin не генерирует мост-метод для специализации ковариантного метода. Я зарегистрировал проблему в системе отслеживания ошибок Kotlin: https://youtrack.jetbrains.com/issue/KT-33634

В качестве обходного пути Jdbi мог эмулировать необходимый метод моста. Необходимый код, вероятно, окажется небольшим, но его очень сложно написать. Я надеюсь, что Котлин, по крайней мере, скоро оценит проблему.

@stevenschlansker Спасибо, что
У Котлина, должно быть, был этот мост раньше, потому что я видел, как он работает. - Это объясняет, почему я не смог заставить его снова работать, вернувшись к более старым версиям JDBI.

Похоже, это был компромисс для обеспечения совместимости с Java 6: 6 не поддерживал методы моста в интерфейсах, поэтому Kotlin их не генерирует. В наши дни это звучит очень глупо, но, вероятно, имело смысл 10 лет назад;) Надеюсь, они скоро откажутся от поддержки 6 или, по крайней мере, условно включат совместимость с миром после 6.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги