Как мне создать составной первичный ключ, используя GORM? - PullRequest
5 голосов
/ 31 марта 2011

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

Я хочу, чтобы таблица Review создала отношения между многими Beer и Reviewer, поэтому я хочу, чтобы первичный ключ Review былсмесь полей идентификаторов от 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.Это позаботилось об ошибке, но когда я смотрю в базу данных, я все еще не получаю составной первичный ключ.

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

       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).Я хотел бы указать порядок столбцов в индексе.

Ответы [ 3 ]

2 голосов
/ 01 апреля 2011

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

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

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

2 голосов
/ 12 сентября 2011

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

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

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

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

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

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

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

0 голосов
/ 31 марта 2011

Попробуйте, в вашем домене Просмотрите класс домена:

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

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

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

...