ORM은 Object Relational Mapping으로 객체를 관계형 데이터베이스에 연결(mapping)하는 것을 의미한다.
ORM의 구현 방식은 다양하게 존재하는데, Active Record와 Data Mapper가 이에 해당한다.
데이터베이스 model이 데이터에 접근
모든 query method들을 model 그 자체에 정의하고, model method를 이용하여 object들을 저장, 갱신, 삭제하도록 한다.
즉, active record는 model을 이용하여 데이터베이스를 조작하기 때문에 SQL을 직접 사용하지 않으면서 데이터 조작이 가능하다.
Active Record는 직관적으로 동작하기 때문에 쉽게 시작하기에 용이하다.
각 모델들은 Base Active Record를 상속받아 구현되어 Base class의 method들을 사용할 수 있다.
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
// model 내부에 query method가 존재함
static findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
}
}
데이터베이스와 model을 분리시켜 mapper가 model과 데이터베이스 사이에 데이터를 이동
모든 query method들을 repository라는 각각의 구분된 class로 나누어 정의하고, repository를 이용하여 object들을 저장, 갱신, 삭제하도록 한다.
Data Mapper를 사용하게 되면 도메인 객체는 데이터베이스에 어떻게 저장되는지 알 필요가 없다.
다만 데이터베이스와 통신을 할 때 Active Record를 사용할 때보다 엄격한 방식으로 진행해야한다.
Active Record와 다르게 Data Mapper는 Base Acrive Record를 상속받지 않기 때문에 상대적으로 가벼운 객체를 가지게 된다.
Entity 👇
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
}
Repository 👇
// 데이터베이스에 관련한 로직이 model이 아닌 repository라는 별도의 class에 구현됨
@EntityRepository()
export class UserRepository extends Repository<User> {
findByName(firstName: string, lastName: string) {
return this.createQueryBuilder("user")
.where("user.firstName = :firstName", { firstName })
.andWhere("user.lastName = :lastName", { lastName })
.getMany();
}
}