Как реализовать ManyToMany в r2dbc

R2DBC в настоящее время не поддерживает составные ключи. Интересно, как мы можем сейчас реализовать отношения «многие ко многим»?

Например, учитывая две сущности:

@Table
class Item(
  @Id var id: Long?,
  var title: String,
  var description: String,
)

@Table
class Tag(
  @Id
  var id: Long?,
  var title: String,
  var color: String,
)

и их схемы:

CREATE TABLE item (
    id                  SERIAL PRIMARY KEY  NOT NULL,
    title               varchar(100)        NOT NULL,
    description         varchar(500)        NOT NULL
);

CREATE TABLE tag (
    id                  SERIAL PRIMARY KEY  NOT NULL,
    title               varchar(100)        NOT NULL,
    color               varchar(6)          NOT NULL
);

Я могу создать таблицу для сопоставления "многие-ко-многим":

CREATE TABLE item_tag (
    item_id bigint  NOT NULL,
    tag_id  bigint  NOT NULL,
    PRIMARY KEY(item_id, tag_id)
);

Но как нам определить класс сопоставления ItemTag в kotlin / java?

@Table
class ItemTag(
  // ??????????????????????? @Id ?????????????????????
  var itemId: Long,
  var tagId: Long,
)

Или можно опустить @Id? Тогда не может быть Repository для класса? Думаю, это было бы хорошо. Это единственный вывод?


person Stuck    schedule 11.03.2021    source источник
comment
В отличие от реализации JPA, в R2DBC нет сопоставления отношений. Если хотите, вам придется загружать отношения вручную. В зависимости от используемой базы данных есть несколько способов сделать это.   -  person nicholasnet    schedule 13.04.2021
comment
Я знаю, но как запросить таблицу ItemTag без добавления поля идентификатора? Без поля идентификатора я не могу создать репозиторий. Вот в чем вопрос.   -  person Stuck    schedule 13.04.2021
comment
О, хорошо, я бы использовал @Transient вместо @ID и загрузил бы объект, так как Composite key еще не поддерживается, я думаю.   -  person nicholasnet    schedule 14.04.2021
comment
Как бы вы построили запрос? без репозитория?   -  person Stuck    schedule 14.04.2021
comment
Просто используйте простой интерфейс, а не CrudRepository, и используйте DatabaseClient для реализации. Дайте мне знать, если вам понадобится какой-либо пример.   -  person nicholasnet    schedule 14.04.2021
comment
Пример был бы отличным! И вы бы все равно поместили аннотацию @Table на объект?   -  person Stuck    schedule 14.04.2021


Ответы (1)


Могут быть другие способы сделать это. Поскольку CompositeKey еще не поддерживается в R2DBC, я думаю. Следовательно, это лишь один из способов решения вашей проблемы.

Класс данных

data class ItemTag(val itemId: Long, val tagId: Long)

Затем репозиторий

interface TagRepository {

    fun getItemTagByTagId(tagId: Long): Flow<ItemTag>
}

Repostory Impl

@Repository
class TagRepositoryImpl(private val databaseClient: DatabaseClient) : TagRepository {
    
    override fun getItemTagByTagId(tagId: Long): Flow<ItemTag> {

        return databaseClient.sql("SELECT * FROM item_tag WHERE tag_id = :tagId")
                             .bind("tagId", tagId)
                             .map(row, _ -> rowToItemTag(row))
                             .all()
                             .flow() 
    }

    private fun rowToItemTag(row: Row): ItemTag {

        return ItemTag(row.get("item_id", Long::class.java)!!, row.get("tag_id", Long::class.java)!!)
    }
    
}

Что-то подобное.

person nicholasnet    schedule 14.04.2021