fontcolor_theme
Deepkit ORM

リレーション

リレーションは、2つのエンティティを特定の方法で関連付けることができます。これは通常、データベースでは外部キーの概念を用いて行われます。Deepkit ORM は公式のすべてのデータベースアダプタでリレーションをサポートします。

リレーションは Reference デコレータで注釈付けします。通常、リレーションには逆方向のリレーションもあり、これは BackReference 型で注釈付けしますが、データベースクエリで逆方向のリレーションを使用する場合にのみ必要です。バックリファレンスは仮想的なものに過ぎません。

1対多

参照を保持するエンティティは、通常 owning side、または参照を owns している側と呼ばれます。次のコードは UserPost の間の 1対多のリレーションを示します。これは、1人の User が複数の Post を持てることを意味します。post エンティティは post->user リレーションを持ちます。データベースには Post."author" フィールドが作成され、そこに User の主キーが格納されます。

import { SQLiteDatabaseAdapter } from '@deepkit/sqlite';
import { entity, PrimaryKey, AutoIncrement, 
    Reference } from '@deepkit/type';
import { Database } from '@deepkit/orm';

@entity.collection('users')
class User {
    id: number & PrimaryKey & AutoIncrement = 0;
    created: Date = new Date;

    constructor(public username: string) {
    }
}

@entity.collection('posts')
class Post {
    id: number & PrimaryKey & AutoIncrement = 0;
    created: Date = new Date;

    constructor(
        public author: User & Reference,
        public title: string
    ) {
    }
}

const database = new Database(
    new SQLiteDatabaseAdapter(':memory:'), 
    [User, Post]
);
await database.migrate();

const user1 = new User('User1');
const post1 = new Post(user1, 'My first blog post');
const post2 = new Post(user1, 'My second blog post');

await database.persist(user1, post1, post2);

参照は、デフォルトではクエリで選択されません。詳細は データベースの結合 を参照してください。

多対1

参照には通常、多対1と呼ばれる逆参照があります。これはデータベース自体には反映されないため、仮想的な参照に過ぎません。バックリファレンスは BackReference で注釈付けされ、主にリフレクションとクエリの結合に使用されます。User から Post への BackReference を追加すると、User のクエリから直接 Post を結合できます。

@entity.name('user').collection('users')
class User {
    id: number & PrimaryKey & AutoIncrement = 0;
    created: Date = new Date;

    posts?: Post[] & BackReference;

    constructor(public username: string) {
    }
}
//[ { username: 'User1', posts: [ [Post], [Post] ] } ]
const users = await database.query(User)
    .select('username', 'posts')
    .joinWith('posts')
    .find();

多対多

多対多リレーションでは、多くのレコードを他の多くのレコードに関連付けることができます。たとえば、ユーザーとグループに使用できます。ユーザーは 0 個、1 個、または複数のグループに所属できます。結果として、グループも 0 人、1 人、または複数のユーザーを含むことができます。

多対多のリレーションは通常、ピボットエンティティを使用して実装します。ピボットエンティティは 2 つの他のエンティティへの実際の所有側の参照を保持し、これら 2 つのエンティティはピボットエンティティへのバックリファレンスを持ちます。

@entity.name('user')
class User {
    id: number & PrimaryKey & AutoIncrement = 0;
    created: Date = new Date;

    groups?: Group[] & BackReference<{via: typeof UserGroup}>;

    constructor(public username: string) {
    }
}

@entity.name('group')
class Group {
    id: number & PrimaryKey & AutoIncrement = 0;

    users?: User[] & BackReference<{via: typeof UserGroup}>;

    constructor(public name: string) {
    }
}

// ピボットエンティティ
@entity.name('userGroup')
class UserGroup {
    id: number & PrimaryKey & AutoIncrement = 0;

    constructor(
        public user: User & Reference,
        public group: Group & Reference,
    ) {
    }
}

これらのエンティティを使って、ユーザーとグループを作成し、ピボットエンティティでそれらを関連付けられます。User にバックリファレンスを使用することで、User のクエリでグループを直接取得できます。

const database = new Database(new SQLiteDatabaseAdapter(':memory:'), [User, Group, UserGroup]);
await database.migrate();

const user1 = new User('User1');
const user2 = new User('User2');
const group1 = new Group('Group1');

await database.persist(user1, user2, group1, new UserGroup(user1, group1), new UserGroup(user2, group1));

//[
//   { id: 1, username: 'User1', groups: [ [Group] ] },
//   { id: 2, username: 'User2', groups: [ [Group] ] }
// ]
const users = await database.query(User)
    .select('username', 'groups')
    .joinWith('groups')
    .find();

ユーザーとグループの関連付けを解除するには、UserGroup レコードを削除します:

const users = await database.query(UserGroup)
    .filter({user: user1, group: group1})
    .deleteOne();

1対1

制約

削除/更新時: RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)