Как использовать аннотацию JDBI @Transaction в неинтерфейсном и неабстрактном классе? - PullRequest
0 голосов
/ 30 апреля 2020

Итак, я родом из Spring Boot, и меня по-настоящему поразило, как аннотация Spring @Transactional без проблем работает вместе с Hibernate. Сейчас я работаю над приложением Dropwizard, которое использует Jdbi3. И я нашел похожую аннотацию @Transaction, которая работает точно так же, как и Spring, но с некоторыми предварительными условиями.

Spring

Таким образом, согласно Spring Guidelines, Repository и Controller - это два интерфейса, которые связываются с базой данных и HTTP-запросами соответственно, Service Layer был местом, где принадлежат все бизнес-логики c. Всегда был случай, когда один метод в службе выполняет операции CRUD с использованием нескольких репозиториев. Поэтому так много смысла делать, чтобы сервисный метод аннотировался с помощью @Transational.

Jdbi с Dropwizard

Так что поправьте меня, если я ошибаюсь. Здесь в Jdbi Repository становится Dao, Controller становится Resource и Service остается Service. Возможно, разные люди используют разные архитектуры слоев, но давайте просто предположим, что именно в этом заключается моя проблема.

Постановка задачи

I wi sh для достижения той же Обработки транзакций в Jdbi, как в идеологическом Spring, потому что это имеет для меня гораздо больше смысла без добавления какого-либо дополнительного слоя. Вот я кидаю какой-то код, которого я * * * * * * * * *

1032 *

 interface Dao1{
    @SqlUpdate("INSERT INTO table1...")
    fun insert() : Int
 }

Dao2.kt

 interface Dao2{
    @SqlUpdate("INSERT INTO table2...")
    fun insert() : Int
 }

Service.kt

class Service{
  @Transaction
  fun save() {
    Dao1 =Dao1() //What should be expected way to instantiate
    Dao2 =Dao2() //What should be expected way to instantiate
    dao1.insert()
    dao2.insert()
  }
}

Несколько замечаний к сведению

  • Я знаю, что onDemand можно использовать только для abstract класса или интерфейса, поэтому я не могу создать экземпляр Service, используя onDemand. Также я не могу сделать свой Service реферат.

  • В нескольких статьях предлагается сделать реферат Repository и использовать там Transaction. Но, как я думаю, когда я думаю о хранилище, я вижу, что у него есть однозначное отображение с entity/table. Или, возможно, связанные лица. Поэтому, если я хочу обновить таблицу movie и user в одном и том же сервисном методе, поместить эти два оператора транзакции в метод в некотором XRepository звучит для меня очень абсурдно. Это часть бизнес-логики c и должна находиться в Service.

  • Я думаю, что я могу использовать jdbi.inTransaction и jdbi.useTransaction. Но в этом случае я должен прикрепить каждый Dao вручную. Есть ли лучший способ сделать это?

Спасибо

1 Ответ

0 голосов
/ 06 мая 2020

Вы можете использовать JDBI @Transaction для украшения метода в ваших bizlogi c классах. Он будет выполнять базовые запросы к базе данных в транзакции.

Предполагая, что Repository может состоять из нескольких Dao's, и предполагая, что поток управления подобен этому, вот один из способов структурирования ваших bizlogi c (бизнес логи c классы) и репозитории.

Resource -> BizLogic -> Repository -> Dao 

Например (Kotlin + Dropwizard + Jdbi):

Resource

    @GET
    @Path("{Id}")
    @Produces(MediaType.APPLICATION_JSON)
    fun getAccount(
            @PathParam("Id") Id: String,
            @Suspended asyncResponse: AsyncResponse
    ) = asyncResponse.with {
        accountManager.getAccount(Id)
    }

метод в BizLogic

    @Transaction
    suspend fun getAccount(Id: String): List<Account> = 
       accountRepository.getAccountsById(Id) ?: emptyList()

метод в Repository

    suspend fun getAccountsById(Id: String): List<Account>? = withContext(Dispatchers.IO){
        accountDao.lookupById(Id)
    }

Dao

        @SqlQuery("select user_id, name, email from users where user_id = :id")
        fun lookupById(@Bind("id") Id: String): List<Account>?

Ps: вам нужно будет обработать привязку репозитория / dao к экземпляру jdbi с помощью guice или spring-di

...