Как создать составной первичный ключ с помощью GORM?

У меня есть три доменных класса: Beer, Review и Reviewer.

Я хочу, чтобы таблица Review создавала отношения «многие ко многим» между Beer и Reviewer, поэтому я хочу, чтобы первичный ключ Review был составным из полей id из Beer и Reviewer. Я следую этой документации Grails.

http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20(GORM).html#5.5.2.5%20Composite%20Primary%20Keys

Вот мои доменные классы.

class Beer {
    String name
    String type
    Brewery breweryId

    static hasMany = [ reviews : Review ]

    static constraints = {
    }
}

class Reviewer {
    String screenName

    static hasMany = [ reviews : Review ]

    static constraints = {
    }
}

class Review implements Serializable {
    int score
    Beer beer
    Reviewer reviewer


    static constraints = {
    }

    static mapping = {
        id composite:['beer', 'reviewer']
    }
}

Я получал ошибки компиляции, но в другом ответе здесь, в stackoverflow, говорилось, что мне нужно добавить implements Serializable. Это устранило ошибку, но когда я смотрю в базу данных, я все еще не получаю составной первичный ключ.

Вот что я вижу, когда смотрю на определение таблицы. Я использую Постгрес.

       Table "public.review"
   Column    |  Type   | Modifiers 
-------------+---------+-----------
 id          | bigint  | not null
 version     | bigint  | not null
 beer_id     | bigint  | not null
 reviewer_id | bigint  | not null
 score       | integer | not null
Indexes:
    "review_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkc84ef75823f39326" FOREIGN KEY (beer_id) REFERENCES beer(id)
    "fkc84ef7587c483106" FOREIGN KEY (reviewer_id) REFERENCES reviewer(id)

Я был бы рад просто составному индексу с уникальным ограничением, но я тоже не могу понять, как это сделать. Мне удалось создать неуникальный составной индекс, но у него есть две проблемы. Во-первых, он не уникален. Во-вторых, столбцы указываются в индексе в алфавитном порядке (beer_id, reviewer_id). Я хотел бы указать порядок столбцов в индексе.


person haydenmuhl    schedule 31.03.2011    source источник


Ответы (3)


Я реализовал аналогичную ситуацию с некоторыми другими условиями:

  1. Нет hasMany отношений.
  2. Запрос к классу соединения выполняется HQL
  3. Использование более подробного отображения

При такой реализации база данных mysql в порядке. (beer_id,reviewer_id) — первичный ключ.

class Review implements Serializable {

    Beer beer
    Reviewer reviewer

    static Review get(long beerId, long reviewerId) {
        find 'from Review where beer.id=:beerId and reviewer.id=:reviewerId',
            [beerId: beerId, reviewerId: reviewerId]
    }

    static boolean remove(Beer beer, Reviewer reviewer, boolean flush = false) {
        Review instance = Review.findByBeerAndReviewer(beer, reviewer)
        instance ? instance.delete(flush: flush) : false
    }
    ...

    static mapping = {
        table "REVIEW"
        id composite: ['beer', 'reviewer']
        beer(column: "beer_ID")
        reviewer(column: "reviewer_ID")
        version false
    }
}

Я не знаю, что именно вызывает вашу проблему, но надеюсь, что это даст вам некоторое представление о том, где может быть проблема.

person Hoàng Long    schedule 01.04.2011

Я воспринял указание Grails не использовать составные первичные ключи как мудрый совет и избегаю его. Если это так, я считаю, что жизнеспособной альтернативой для решения вашей проблемы является Composite Unique Constraint. ссылка: http://grails.org/doc/1.1.x/ref/Constraints/unique.html

Ответ Джакко кажется неправильным, хотя визуально он выглядит очень близким к правильному, вот как вы бы написали составное уникальное ограничение для этой проблемы:

static constraints = {
    beer(unique: 'reviewer')
}

тогда как, если программист хотел связать 3 поля db как уникальные, правильное формирование:

static constraints = {
    beer(unique: ['anotherField','reviewer'])
}

который выглядит как ответ Jacco, но имя класса не используется в качестве первой строки ограничения, используется имя первого поля.

Я только что использовал эту структуру кода в своем собственном приложении проекта, и, похоже, она ведет себя правильно, см. также это о том, как проводить модульное тестирование уникальных ограничений: http://www.ibm.com/developerworks/java/library/j-grails10209/index.html (см. листинг 11)

person Rob    schedule 12.09.2011

Попробуйте это, в своем домене Обзор класса домена:

static constraints = {
     review(unique: ['beer','reviewer'])
}

возможно, вам придется удалить таблицу и позволить Горму воссоздать ее.

указанное выше ограничение означает, что отзыв должен состоять из уникальной записи комбинации пиво/рецензент. это по-прежнему много ко многим, когда у рецензента есть несколько сортов пива и наоборот, но обзоры уникальны.

person z.eljayyo    schedule 31.03.2011