Desenvolvendo APIs com NestJS + TypeORM — Parte 2

Ana Carolina Manzan
Feb 1 · 7 min read

Olá Dev(a)!

Na segunda parte dessa série de artigos, vamos iniciar a implementação do acesso ao banco de dados com TypeORM.

Image for post
Image for post
Logo do TypeORM

Se você ainda não leu a primeira parte, pode conferir aqui.

Vamos lá!

Criação de entidades

Antes de iniciarmos a criação das nossas entidades, precisamos instalar o TypeORM na nossa aplicação. Para isso, abra o terminal no VS Code (ou no seu editor de preferência) e execute o comando npm install @nestjs/typeorm typeorm. Além disso, precisamos instalar o driver do SQL Server na aplicação, pois é com este banco de dados que trabalharemos. Para isso, execute o comando npm install mssql.

Dentro da pasta src, criaremos a pasta domain e dentro dela, a pasta entities. Na pasta entities, crie três entidades: Book, Author e Status. O resultado será esse:

Image for post
Image for post
Conteúdo da pasta entities no projeto

Poderíamos criar um simples enum para representar o Status? Sim! Mas eu gostaria de mostrar para vocês 2 tipos de relacionamentos com o TypeORM: 1:N (um para muitos) e M:N (muitos para muitos), e por isso decidi fazer do Status uma entidade.

Vamos agora definir o conteúdo de cada uma das nossas entidades:

Entidade Author e suas propriedades
Entidade Book e suas propriedades
Entidade Status e suas propriedades

Perceba que não definimos nenhuma informação sobre os relacionamentos entre as entidades. Como o TypeORM saberá mapear os relacionamentos entre as entidades? Ou melhor, como o TypeORM saberá identificar quais são as entidades que ele deve mapear para o banco de dados? Temos que fazer algumas alterações para que o TypeORM entenda isso!

Decorators

O TypeORM, assim como o NestJS, faz uso de Decorators. É através dos Decorators que vamos apontar para o TypeORM quais são as entidades que ele deve mapear para o banco de dados, quais são as colunas das tabelas, e até mesmo os relacionamentos entre as tabelas. Aqui nesse artigo, veremos alguns desses Decorators, mas você pode consultar a documentação de referência de todos eles aqui.

Vamos ver agora como ficaram as nossas entidades com os Decorators:

Entidade Author com Decorators
Entidade Book com Decorators
Entidade Status com Decorators

Temos diversos Decorators em nossas entidades, e cada um deles cumpre uma função diferente. Confira uma breve explicação sobre eles:

Entity() É usada para transformar nossa classe em uma entidade. Uma entidade é uma classe que será convertida em tabela no banco de dados. Podemos adicionar outras informações à esse Decorator, como por exemplo, o nome que gostaríamos de dar à tabela no banco de dados. Exemplo: Entity({ name: “books” }).

PrimaryGeneratedColumn(“strategie”) Além de indicar que a coluna em questão se trata de uma chave primária, esse decorator também indica que é um campo gerado automaticamente. Ele pode ser utilizado com 3 opções de geração: increment (para campos numéricos com auto incremento), uuid (para geração automática de GUIDs), e row_id (produz um número de 64 bits baseado no timestamp atual + um id, disponível apenas para CockroachDB).

Column({ options }) Este decorator transforma a propriedade da nossa classe em uma coluna da tabela do banco de dados. Como podemos observar nas entidades acima, podemos definir algumas características da nossa coluna, como o tipo, tamanho, se é uma informação obrigatória ou não, dentre outras.

ManyToOne(), OneToMany() são os decorators que utilizamos quando queremos definir um relacionamento de um para muitos. Neste caso, teremos que um livro terá apenas um status relacionado a ele (lendo, lido, etc), porém um status poderá ser utilizado para vários livros.

JoinColumn() define qual lado da relação contém a coluna com a chave estrangeira, permitindo a personalização do nome da coluna.

RelationId() é um decorator utilizado com uma propriedade na entidade para carregar o id referente aos relacionamentos em uma propriedade específica.

ManyToMany() é o decorator que utilizamos quando queremos definir um relacionamento de muitos para muitos. No caso da nossa aplicação, um autor pode ter escrito vários livros, assim como um livro pode ter sido escrito por vários autores.

JoinTable() quando trabalhamos com um relacionamento de muitos para muitos, esse decorator é utilizado para definir as colunas da tabela de junção do relacionamento. A tabela de junção é uma tabela que é criada automaticamente pelo TypeORM para referenciar as chaves primárias das tabelas presentes no relacionamento.

Banco de dados e Docker

Sim! Para trabalhar com o SQL Server, vamos utilizar o Docker.

Por que utilizar o Docker? Para que possamos utilizar o SQL Server em nossa máquina sem que haja a preocupação de instalar a ferramenta, vamos rodar uma imagem do SQL Server com o Docker. Para isso, faça o download e instalação do Docker.

Depois de instalar o Docker, é preciso inicializá-lo para que possamos fazer o download da imagem do SQL Server. Inicialize o seu Docker, e depois, abra um prompt de comando. No prompt, digite o seguinte comando:

docker pull mcr.microsoft.com/mssql/server

Este comando fará o download da imagem através do Docker. Após a finalização do download, execute o comando docker images, que listará todas as imagens disponíveis no seu computador.

Image for post
Image for post
Resultado da execução do comando docker images

Precisamos agora criar um container baseado nesta imagem que acabamos de baixar:

docker run -e "ACCEPT_EULA=Y" -e "SA_PASSWORD=JdmhwHZM3_Kcb;>6" -p 1433:1433 -d --name=sql_server mcr.microsoft.com/mssql/server

Utilizamos o comando docker run para criar o nosso container. Juntamente com o comando, temos algumas flags:

  • -e: cria variáveis de ambiente para o container. Neste comando criamos duas: "ACCEPT_EULA=Y" para indicar que aceitamos o contrato de licença e "SA_PASSWORD=JdmhwHZM3_Kcb;>6" que é senha do usuário padrão (SA) do sistema de banco de dados para o SQL Server
  • -p: indica em qual porta o container será executado
  • -d: Cria o container com sua execução em background, não travando o nosso terminal no contexto do container
  • --name: Define o nome do container

E por último, temos o nome da imagem que será utilizada para a criação e execução do container: mcr.microsoft.com/mssql/server

Criação do banco de dados

Vamos criar o nosso banco de dados dentro do container, através de linha de comando:

docker exec -it sql_server /opt/mssql-tools/bin/sqlcmd -S "localhost" -U "sa" -P "JdmhwHZM3_Kcb;>6" -Q "CREATE DATABASE BookShelfDb"

A instrução docker exec é utilizada para executar comandos no container em execução. Assim como em outros comandos, também temos alguns parâmetros sendo utilizados na execução deste:

  • -it: Usa o modo iterativo e anexa um terminal
  • sql_server: o nome do container que criamos anteriormente
  • /opt/mssql-tools/bin/sqlcmd: Caminho da ferramenta de linha de comando sqlcmd no contêiner
  • -S “server”: Servidor
  • -U “user”: Usuário
  • -P “password”: Senha
  • -Q “query”: Query a ser executada com a ferramente de linha de comando do sqlcmd

(Referência: Docker — Executando o SQL Server em um Contêiner no Linux)

TypeOrmConfig

Além de todos os Decorators que vimos anteriormente, o TypeORM também precisa de outras informações pertinentes ao nosso banco de dados, para acessá-lo: endereço do host, usuário para acesso ao banco, senha, nome do banco, dentre outros.

Para isso, criaremos um arquivo chamado TypeOrmConfig.ts na raíz da nossa aplicação. Definiremos o conteúdo do nosso arquivo de acordo com as informações do container que criamos anteriormente. O resultado será o seguinte:

Conteúdo do arquivo TypeOrmConfig.ts

Criando a nossa primeira Migration

Quando trabalhamos com ORMs, é muito comum fazermos uso de Migrations.

As migrations são utilizadas pelos ORMs para versionar as mudanças relacionadas à estrutura do nosso banco de dados. Elas garantem que o nosso banco de dados irá refletir toda e qualquer mudança presente nas nossas entidades.

E como podemos criar as migrations?

Antes de qualquer coisa, abra o arquivo package.json para adicionarmos 3 scripts que facilitarão esse processo de criação de migrations e atualização do banco de dados. Esses scripts devem ser adicionados na seção “scripts” do arquivo.

Para que os scripts acima funcionem, é necessário instalar o ts-node. Para isso, execute o comando npm install -g ts-node no seu prompt de comando.

Depois disso, dentro da pasta src crie a pasta infra, e dentro dela, a pasta migrations. Agora, vamos abrir o nosso terminal do VS Code, e rodar o seguinte comando:

npm run add-migration "initial-migration"

Depois de executar o comando acima, já teremos em nossa pasta migrations a nossa primeira migration gerada.

Quando abrimos a migration, veremos 2 métodos principais: Up e Down. O método Up contém instruções SQL que vão realizar as alterações pertinentes ao que fizemos em nossas entidades. Já o método Down, irá desfazer estas alterações, caso algum erro ocorra durante a execução do método Up.

Para que esta migration gerada reflita as mudanças no nosso banco de dados, precisamos rodar mais um comando. No seu terminal, execute o comando npm run update-database para isso. Se obtivermos sucesso na operação, a mensagem exibida será mais ou menos assim:

Image for post
Image for post
Mensagem do terminal indicando sucesso na execução da migration

E prontinho! Depois de todos estes passos, teremos o nosso banco de dados pronto para trabalhar com a aplicação.

Você pode fazer o download do que foi desenvolvido neste projeto até o momento através deste link do meu GitHub.

Na próxima parte da série, vamos começar a desenvolver nossos repositórios e endpoints da API.

Até mais! 👩‍💻

anamanzandev

Desenvolvimento de software

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store