React Native では TypeORM を使って端末の SQLite を操作できます。 SQLite 3 からは Relation も定義できます。
この記事では、以下のような 1対多、 多対1の関係を持つ Entity をテーブルに保存する方法を紹介します。
Entity の定義
@OneToMany()
, @ManyToOne()
の Entity を定義します。
SnapShot.ts
import {Column, Entity, ManyToOne, OneToMany, PrimaryColumn} from "typeorm";
@Entity('snap_shots')
export class SnapShot {
@PrimaryColumn({ type: "varchar"})
id: string
@PrimaryColumn({ type: "varchar"})
date: string
@Column({type: "int", default: 0})
totalTaskTime: number
@OneToMany(() => SnapShotTask, snapShotTask => snapShotTask.snapShot, {cascade: true})
snapShotTasks: SnapShotTask[];
}
@Entity('snap_shot_tasks')
export class SnapShotTask {
@PrimaryColumn({ type: "varchar"})
id: string
@Column({ type: "varchar"})
name: string
@Column({ type: "int", default: 0})
totalTime: number
@ManyToOne(() => SnapShot, snapShot => snapShot.snapShotTasks, )
snapShot: SnapShot;
}
テーブルを操作する関数を定義する
テーブルを操作する関数を作ります(今回のサンプルで使うものに限定しています)
snapshotRepository.ts
export const getSnapShots = async () => {
const snapShotRepository = AppDataSource.getRepository(SnapShot);
return await snapShotRepository.find({
relations: {
snapShotTasks: true,
},
});
};
export const getSnapShotByDateString = async (date: string) => {
const snapShotRepository = AppDataSource.getRepository(SnapShot);
return await snapShotRepository.findOne({ where: { date }, relations: ['snapShotTasks'] });
};
export const addSnapShot = async (snapShot: SnapShot) => {
const snapShotRepository = AppDataSource.getRepository(SnapShot);
return await snapShotRepository.save(snapShot);
};
find
メソッドを呼ぶときは、 relations: { xxx: true }
を指定する必要があります。
https://orkhan.gitbook.io/typeorm/docs/find-options
上記のテーブルを操作する関数を使ってテーブルにリレーションを保存する関数は以下のとおりです。
sample.ts
export async function recordResults(tasks: Task[], dateString: string) {
const snapShotByDate = await getSnapShotByDateString(dateString);
const snapShot = new SnapShot();
snapShot.id = snapShotByDate === null ? uuidv4() : snapShotByDate.id;
snapShot.date = dateString;
snapShot.totalTaskTime = tasks.reduce((acc, task) => acc + task.totalTime, 0);
// 親に子の配列のプロパティを設定する
snapShot.snapShotTasks = tasks.map((task) => {
const snapShotTask = new SnapShotTask();
snapShotTask.id = uuidv4();
snapShotTask.name = task.name;
snapShotTask.totalTime = task.totalTime;
snapShotTask.snapShot = snapShot;
return snapShotTask;
});
// 親を保存する
await addSnapShot(snapShot);
// 結果を確認する
const result = await getSnapShotByDateString(dateString);
if (result !== null) {
console.log('result:', result);
result.snapShotTasks.forEach((snapShotTask) => {
console.log(`タスク: ${snapShotTask.name} - ${result.id}`);
});
}
}
上の例だと、「同じ日付につき1つの SnapShot を保存する」ために、 snapShot.id = snapShotByDate === null ? uuidv4() : snapShotByDate.id;
などとやっていますが、この辺は自分が作っているアプリの仕様なので、不要なときは無視してください。
ポイントは、「親のプロパティに子の配列を設定すること」→その後で「親を保存すること」です。
また getSnapShotByDateString
という関数で relation
を設定している点にも注目です。関連を貼ったテーブルの情報を取得するには relation
を指定しなければいけません。指定する文字列は子との関連を定義している「プロパティ名」です。