GrailsのGORMにおける各種関連とmappingによる名前変更のサンプル

Grailsのドキュメントを翻訳する上で、英文読んでも何を言ってるか分からないので、サンプル書いて試してみた記録です。

↓ここに反映される予定。

生成されたスキーマPostgreSQLにて確認してあります。 異なるDBMSなら異なるスキーマになることもあるかも知れません。Hibernateのみぞ知る。

多対1/1対1関連(単方向)

基本

ドメインクラス

class Person {

    String firstName
    Address address

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
    }
}
class Address {

    String number
    String postCode

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 address_id | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkc4e2328f2efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people" CONSTRAINT "fkc4e2328f2efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

Person上のaddressカラムのマッピングを変更してみる

ドメインクラス

class Person {

    String firstName
    Address address

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
        address column: 'Person_Address_Id' // コレの効果は...?
    }
}
class Address {

    String number
    String postCode

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

                 Table "public.people"
      Column       |          Type          | Modifiers
-------------------+------------------------+-----------
 id                | bigint                 | not null
 version           | bigint                 | not null
 person_address_id | bigint                 | not null  <-------- ココが変わった!!!
 first_name        | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkc4e2328fec329d0d" FOREIGN KEY (person_address_id) REFERENCES address(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people" CONSTRAINT "fkc4e2328fec329d0d" FOREIGN KEY (person_address_id) REFERENCES address(id)

多対1/1対1関連(双方向)

基本

ドメインクラス

class Person {

    String firstName
    Address address

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
    }
}
class Address {

    String number
    String postCode

    static belongsTo = [person:Person]

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

単方向の場合とスキーマは同じ。

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 address_id | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkc4e2328f2efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:    TABLE "people" CONSTRAINT "fkc4e2328f2efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

Person上のaddressカラムのマッピングを変更してみる

単方向の場合とスキーマは同じなので、後は...わかりますね?

1対多関連(単方向)

基本

ドメインクラス

class Person {

    String firstName

    static hasMany = [addresses: Address]

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
    }
}
class Address {

    String number
    String postCode

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people_address" CONSTRAINT "fk3af1764434f4e10e" FOREIGN KEY (person_addresses_id) REFERENCES people(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people_address" CONSTRAINT "fk3af176442efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

      Table "public.people_address"
       Column        |  Type  | Modifiers
---------------------+--------+-----------
 person_addresses_id | bigint |
 address_id          | bigint |
Foreign-key constraints:
    "fk3af176442efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)
    "fk3af1764434f4e10e" FOREIGN KEY (person_addresses_id) REFERENCES people(id)

Person上のaddressesカラムのマッピングを変更してみる

ドメインクラス

class Person {

    String firstName

    static hasMany = [addresses: Address]

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
        addresses column: 'Person_Address_Id' // コレの効果は...?
    }
}
class Address {

    String number
    String postCode

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:    "people_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people_address" CONSTRAINT "fk3af17644e3b329fc" FOREIGN KEY (person_address_id) REFERENCES people(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "people_address" CONSTRAINT "fk3af176442efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

     Table "public.people_address"
      Column       |  Type  | Modifiers
-------------------+--------+-----------
 person_address_id | bigint |              <-------- ココが変わった!!!
 address_id        | bigint |
Foreign-key constraints:
    "fk3af176442efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)
    "fk3af17644e3b329fc" FOREIGN KEY (person_address_id) REFERENCES people(id)

関連テーブル自体を指定する

ドメインクラス

class Person {
    String firstName

    static hasMany = [addresses: Address]

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
        addresses joinTable: [name: 'Person_Addresses',
                              key: 'Person_Id',
                              column: 'Address_Id'] // コレの効果は...?
    }
}
class Address {

    String number
    String postCode

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "person_addresses" CONSTRAINT "fk8aeab389671fd1" FOREIGN KEY (person_id) REFERENCES people(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "person_addresses" CONSTRAINT "fk8aeab382efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)

 Table "public.person_addresses"   <-------- ココが変わった!!!
   Column   |  Type  | Modifiers
------------+--------+-----------
 person_id  | bigint | not null    <-------- ココが変わった!!!
 address_id | bigint |
Foreign-key constraints:
    "fk8aeab382efad9e3" FOREIGN KEY (address_id) REFERENCES address(id)
    "fk8aeab389671fd1" FOREIGN KEY (person_id) REFERENCES people(id)

1対多関連(双方向)

基本

ドメインクラス

class Person {

    String firstName

    static hasMany = [addresses: Address]

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
        addresses cascade: "all-delete-orphan"
    }
}
class Address {

    String number
    String postCode

    static belongsTo = [person:Person]

    static mapping = {
        postCode type: 'text'
    }
}

生成されたスキーマ

関連テーブルなしに、子テーブル側に親へのIDを保持するスキーマとなる。 「双方向」であるため、晴れて子から親を参照してもOKになるので、関連テーブルを導入するまでもなく、単に親 のIDを持つスキーマ構造が採用できる、ということと推測するが...。

              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "address" CONSTRAINT "fkbb979bf49671fd1" FOREIGN KEY (person_id) REFERENCES people(id)

             Table "public.address"
  Column   |          Type          | Modifiers
-----------+------------------------+-----------
 id        | bigint                 | not null
 version   | bigint                 | not null
 number    | character varying(255) | not null
 person_id | bigint                 | not null
 post_code | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkbb979bf49671fd1" FOREIGN KEY (person_id) REFERENCES people(id)

Person上のaddressesカラムのマッピングを変更してみる

ドメインクラス

class Person {

    String firstName

    static hasMany = [addresses: Address]

    static mapping = {
        table 'people'
        firstName column: 'First_Name'
        addresses cascade: "all-delete-orphan",
                  column: 'Person_Address_Id' // こっちに書いても効かない(エラーにならず単に無視された)
    }
}
class Address {

    String number
    String postCode

    static belongsTo = [person:Person]

    static mapping = {
        postCode type: 'text'
        person column: "my_person_id" // コレの効果は...?
    }
}

生成されたスキーマ

hoge=# \d people              Table "public.people"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "people_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "address" CONSTRAINT "fkbb979bf4576400fe" FOREIGN KEY (my_person_id) REFERENCES people(id)

hoge=# \d address
              Table "public.address"
    Column    |          Type          | Modifiers
--------------+------------------------+-----------
 id           | bigint                 | not null
 version      | bigint                 | not null
 number       | character varying(255) | not null
 my_person_id | bigint                 | not null <-------- ココが変わった!!!
 post_code    | text                   | not null
Indexes:
    "address_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "fkbb979bf4576400fe" FOREIGN KEY (my_person_id) REFERENCES people(id)

多対多関連(双方向)

基本

ドメインクラス

class Group {

    String name

    static hasMany = [people: Person]

    static mapping = {
       table 'my_group' // PostgreSQLでは'group'テーブルを作成しようとするとエラーになる
    }
}
class Person {
    String firstName

    static hasMany = [groups: Group]
    static belongsTo = Group
}

生成されたスキーマ

           Table "public.my_group"
 Column  |          Type          | Modifiers
---------+------------------------+-----------
 id      | bigint                 | not null
 version | bigint                 | not null
 name    | character varying(255) | not null
Indexes:    "my_group_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "my_group_people" CONSTRAINT "fk7525b002f314e043" FOREIGN KEY (group_id) REFERENCES my_group(id)

              Table "public.person"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not nullIndexes:
    "person_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "my_group_people" CONSTRAINT "fk7525b0029671fd1" FOREIGN KEY (person_id) REFERENCES person(id)

 Table "public.my_group_people"
  Column   |  Type  | Modifiers
-----------+--------+-----------
 group_id  | bigint | not null
 person_id | bigint | not null
Indexes:
    "my_group_people_pkey" PRIMARY KEY, btree (group_id, person_id)
Foreign-key constraints:
    "fk7525b0029671fd1" FOREIGN KEY (person_id) REFERENCES person(id)
    "fk7525b002f314e043" FOREIGN KEY (group_id) REFERENCES my_group(id)

外部キーカラム名を変更する

ドメインクラス

class Group {

    String name

    static hasMany = [people: Person]

    static mapping = {
       table 'my_group'
       people column: 'Group_Person_Id' // コレの効果は...?
    }
}
class Person {
    String firstName

    static hasMany = [groups: Group]
    static belongsTo = Group

    static mapping = {
       groups column: 'Group_Group_Id' // コレの効果は...?
    }
}

生成されたスキーマ

           Table "public.my_group"
 Column  |          Type          | Modifiers
---------+------------------------+-----------
 id      | bigint                 | not null
 version | bigint                 | not null name    | character varying(255) | not null
Indexes:
    "my_group_pkey" PRIMARY KEY, btree (id)Referenced by:
    TABLE "my_group_people" CONSTRAINT "fk7525b0027e1c21ed" FOREIGN KEY (group_person_id) REFERENCES my_group(id)

              Table "public.person"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:
    "person_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "my_group_people" CONSTRAINT "fk7525b00253631627" FOREIGN KEY (group_group_id) REFERENCES person(id)

    Table "public.my_group_people"
     Column      |  Type  | Modifiers
-----------------+--------+-----------
 group_person_id | bigint | not null <-------- ココが変わった!!!
 group_group_id  | bigint | not null <-------- ココが変わった!!!
Indexes:
    "my_group_people_pkey" PRIMARY KEY, btree (group_person_id, group_group_id)
Foreign-key constraints:
    "fk7525b00253631627" FOREIGN KEY (group_group_id) REFERENCES person(id)
    "fk7525b0027e1c21ed" FOREIGN KEY (group_person_id) REFERENCES my_group(id)

関連テーブル名を指定する

ドメインクラス

class Group {

    String name

    static hasMany = [people: Person]

    static mapping = {
       table 'my_group'
       people column: 'Group_Person_Id',
              joinTable: 'PERSON_GROUP_ASSOCIATIONS' // コレの効果は...?
    }
}
class Person {
    String firstName

    static hasMany = [groups: Group]
    static belongsTo = Group

    static mapping = {
       groups column: 'Group_Group_Id',
              joinTable: 'PERSON_GROUP_ASSOCIATIONS' // コレの効果は...?
    }
}

生成されたスキーマ

           Table "public.my_group"
 Column  |          Type          | Modifiers
---------+------------------------+-----------
 id      | bigint                 | not null
 version | bigint                 | not null
 name    | character varying(255) | not null
Indexes:    "my_group_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "person_group_associations" CONSTRAINT "fk9dd6e6fc7e1c21ed" FOREIGN KEY (group_person_id) REFERENCES my_group(id)

              Table "public.person"
   Column   |          Type          | Modifiers
------------+------------------------+-----------
 id         | bigint                 | not null
 version    | bigint                 | not null
 first_name | character varying(255) | not null
Indexes:    "person_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "person_group_associations" CONSTRAINT "fk9dd6e6fc53631627" FOREIGN KEY (group_group_id) REFERENCES person(id)

Table "public.person_group_associations" <-------- ココが変わった!!!
     Column      |  Type  | Modifiers
-----------------+--------+-----------
 group_group_id  | bigint | not null
 group_person_id | bigint | not null
Indexes:
    "person_group_associations_pkey" PRIMARY KEY, btree (group_person_id, group_group_id)
Foreign-key constraints:
    "fk9dd6e6fc53631627" FOREIGN KEY (group_group_id) REFERENCES person(id)
    "fk9dd6e6fc7e1c21ed" FOREIGN KEY (group_person_id) REFERENCES my_group(id)