Progressive Full Stack Application Development with Live Projects

ORM

TypeORM Relations for a Learning Management System

Introduction

TypeORM is an Object-Relational Mapper (ORM) for TypeScript and JavaScript that simplifies interaction with relational databases. It provides decorators to define relations between different entities or tables, making it easy to handle complex data models.

TypeORM Decorators for Relations

  • @OneToMany: This defines a one-to-many relationship where one entity can have multiple related entities. For example, one Course can have multiple Lessons.
  • @ManyToOne: This defines the inverse side of @OneToMany. For example, many Lessons belong to one Course.
  • @ManyToMany: This defines a many-to-many relationship. In the case of User and Course, a user can be enrolled in many courses, and a course can have many users. This relationship will require a join table to track the associations.
  • @JoinTable: This decorator is required for many-to-many relationships to specify the table that holds the foreign keys linking the two entities.

A Typical Learning Management System (LMS)

In a Learning Management System (LMS), we typically have entities like User, Course ,Lesson, Enrollment, and Assignment, Grade, which can have various relationships. Let us analyze this relational database design step-by-step with source code of TypeORM Entities.

Entities in the Learning Management System

So a database table (SQL) is represented as an Entity Class (TypeORM).

Let us start creating entities and manage relationships. The relationships between entities like User, Course, Enrollment, and Assignment are represented by decorators like @OneToMany, @ManyToOne, and @ManyToMany.

Entity Relations in the Learning Management System

1. User Entity

The User entity represents a user in the system. A user can be either a student or an instructor. Each user can enroll in multiple courses.

				
					import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  ManyToMany,
  JoinTable,
} from 'typeorm';
import { Enrollment } from './Enrollment';
import { Course } from './Course';

@Entity()
export class User {
  //Primary column of table with autoincrement
  @PrimaryGeneratedColumn()
  id: number;

  //other column
  @Column()
  name: string;

  @Column()
  email: string;

  //This user can have many courses
  @OneToMany(() => Enrollment, (enrollment) => enrollment.user)
  enrollments: Enrollment[];

  @ManyToMany(() => Course)
  @JoinTable() // This creates a join table for the many-to-many relation
  courses: Course[];
}

				
			

2. Course Entity

A Course can have many Lessons and can be enrolled by many Users.

				
					import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  ManyToMany,
} from 'typeorm';
import { Lesson } from './Lesson';
import { User } from './User';
import { Enrollment } from './Enrollment';

@Entity()
export class Course {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @OneToMany(() => Lesson, (lesson) => lesson.course)
  lessons: Lesson[];

  @ManyToMany(() => User)
  users: User[];

  @OneToMany(() => Enrollment, (enrollment) => enrollment.course)
  enrollments: Enrollment[];
}

				
			

3. Lesson Entity

A Lesson is linked to a Courseand a course can have multiple lessons.

				
					import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
} from 'typeorm';
import { Course } from './Course';

@Entity()
export class Lesson {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column()
  content: string;

  @ManyToOne(() => Course, (course) => course.lessons)
  course: Course;
}

				
			

4. Enrollment Entity

The Enrollment entity represents a relationship between a student and a course. A student can enroll in multiple courses.

				
					import {
  Entity,
  PrimaryGeneratedColumn,
  ManyToOne,
  JoinColumn,
} from 'typeorm';
import { User } from './User';
import { Course } from './Course';

@Entity()
export class Enrollment {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(() => User, (user) => user.enrollments)
  @JoinColumn()
  user: User;

  @ManyToOne(() => Course, (course) => course.enrollments)
  @JoinColumn()
  course: Course;
}
				
			

5. Assignment Entity

The Assignment entity represents an assignment for a specific course. In this example, an instructor can create many assignments for a course.

				
					import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { Course } from './Course';

@Entity()
export class Assignment {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column()
  dueDate: Date;

  @ManyToOne(() => Course, (course) => course.assignments)
  course: Course;
}

				
			

6. Grade Entity

A Grade represents the score given to a user for a particular Assignment.

				
					import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
} from 'typeorm';
import { Assignment } from './Assignment';
import { User } from './User';

@Entity()
export class Grade {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  score: number;

  @ManyToOne(() => Assignment, (assignment) => assignment.grades)
  assignment: Assignment;

  @ManyToOne(() => User, (user) => user.grades)
  user: User;
}

				
			

By using these relations, we can easily query for courses a user is enrolled in, assignments for a course, or even the instructor of a course. TypeORM handles the complexities of joining tables automatically behind the scenes.