Baixe o app para aproveitar ainda mais
Prévia do material em texto
7ºAula Node.js e MySQL Objetivos de aprendizagem Ao término desta aula, vocês serão capazes de: • construir uma API que retorna JSON; • criar um CRUD com Node.js e MySQL. Olá, Sejam bem-vindos(as) à penúltima aula da disciplina Desenvolvimento Voltado à Web III. Na aula anterior, os WebSocktes foram definidos e exemplificados. Eles são ferramentas que garantem uma conexão bidirecional permanente entre cliente e servidor, podendo ser utilizados em chats e jogos online que demandam baixa latência na troca de informações. Nesta aula utilizaremos o Node.js para se conectar ao banco de dados MySQL e efetuar operações de Seleção, Inserção, Remoção e Atualização dos dados. Boa aula! Bons estudos! 143 Desenvolvimento Voltado a Web III 50 1 – Usando o MySQL no Node.js 2 – O que é CRUD? 3 – Construindo uma API 1 - Usando o MySQL no Node.js O MySQL é um SGBD publicado em 1995 pela empresa MySQL AB, adquirida pela Sun Microsystem que foi incorporada pela Oracle. Esta última mantém uma versão gratuita que pode ser utilizada pela comunidade em geral. Antes de iniciar a conexão do MySQL com o Node. js é preciso que tenha o MySQL devidamente instalado. A Oracle disponibiliza uma versão denominada Edição da Comunidade, que quando instalada corretamente, possui o Além disso, é importante ter um banco de dados criado para que seja possível fazer os testes e criação da API, como veremos mais adiante. Nos materiais de aula serão disponibilizadas tutoriais para instalação do MySQL, além de um banco de dados de exemplo. iniciar a conexão do Node.js com o MySQL. Para instalar o módulo que irá fazer a comunicação entre nossa aplicação e o MySQL utilizamos o seguinte comando no prompt. npm install mysql --save Esse módulo possui o driver do MySQL. Para usá- los carregamos, então, o módulo para o nosso código e instanciamos um objeto, que será a conexão com o MySQL, através do método createConnection(), passando por parâmetros as informações de nosso banco de dados, tais como, usuário, senha, banco de dados e host. var con = mysql.createConnection({ host: “localhost”, user: “seuusuario”, password: “suasenha”, database: “seubancodedados” }); Feita a chamada para se criar a conexão ela irá disparar um evento, o método connect(), que poderá tratar erros caso não tenha sido possível fazer a conexão com o MySQL. con.connect(function(err) { if (err) throw err; console.log(“Conectado!”); }); Um detalhe muito importante, se no seu banco de dados Seções de estudo MySQL a partir da versão 8.0 você usa a senha padrão para o usuário root, o erro “ER_NOT_SUPPORTED_AUTH_ MODE” irá ocorrer. Figura 1 – Erro Auth Mode Mysql. Fonte: Acervo pessoal. MySQL. Para isso você pode executar o seguinte comando diretamente no MySQL Workbench. IDENTIFIED WITH mysql_native_ Dessa forma, o usuário root passará a usar a senha `123456789`, possibilitando a conexão com o MySQL. Figura 2 – MySQL conectado. Fonte: Acervo pessoal. Depois que o Node.js conseguiu se conectar com sucesso ao MySQL, podemos executar o SQL, seja ele qual for, através do método query(), feito pelo objeto instanciado com a conexão. Ao realizar o comando, a função que é retornada tem a possibilidade de tratar algum erro que possa ter dado nessa execução ou retornar o resultado do SQL no console. con.query(sql, function (err, result) { if (err) throw err; console.log(“Result: “ + result); }); 2 Create, Read, Update e Delete. A partir das letras iniciais de cada uma dessas operações temos o acrônimo CRUD. Ele trata das 4 operações básicas de SQL, Insert, Select, Update e Delete, respectivamente. 144 51 Figura 3 – CRUD. Fonte: Acervo pessoal. O paradigma CRUD é muito utilizado na construção de aplicações web, já que permite a manipulação completa do banco de dados. Por exemplo, para construir um dicionário online, o que cada operação do CRUD deveria fazer?: Create Responsável pela inserção de novas palavras, sua esse recurso posteriormente. Criar a palavra Abacaxi. INSERT INTO palavras VALUES (‘Abacaxi’, ‘Planta originária da América tropical.’, ‘Substantivo de dois gêneros’); Read Tem por função retornar as palavras que já foram inseridas no banco de dados, podendo ainda retornar um Abacaxi. Update Atualiza um ou mais atributos de uma ou um conjunto de palavras a partir de uma condição. Atualizar a classe gramatical da palavra Abacaxi. UPDATE palavra SET classe=’Adjetivo de dois gêneros’ WHERE nome=’Abacaxi’; Delete Remove palavras do dicionário de acordo com uma condição. Delete a palavra Abacaxi. DELETE FROM palavra WHERE nome=’Abacaxi’; Para cada uma das ações deve-se retornar o que foi exigido ou se foi possível ou não realizar o comando. 3 - Construindo uma API Pires (2017) explica que uma API (Application Programming Interface) é uma coleção de rotinas e padrões desenvolvidos e documentados, que podem ser utilizados por outras aplicações, sem que estas precisem conhecer a implementação detalhadamente. “APIs permitem uma interoperabilidade entre aplicações”. Fonte: PIRES (2017). O mais importante da API é que ela contenha padrões. Devido a sua interoperabilidade, todas as aplicações devem saber como chamar a API, e o que esperar da resposta dela. A resposta da API pode ser dada em formatos diferentes, pode ser em XML, JSON, YAML. Enquanto o primeiro demanda mais escrita, o segundo e o terceiro são muito mais leves e parecidos, como a forma que escrevemos diariamente. XML <dicionario> <palavra> Abacaxi </palavra> Planta originária da América tropical <classegramatical> </classegramatical> </dicionario> JSON { dicionário: { palavra: Abacaxi da América tropical classegramatical: Substantivo } } YAML dicionário: palavra: Abacaxi da América tropical classegramatical: Substantivo Algumas APIs permitem o retorno em várias representações, sendo passado também por parâmetro a representação desejada, por exemplo a API VIACEP que possibilita a consulta gratuita de CEPs Brasileiros, seja pelo 145 Desenvolvimento Voltado a Web III 52 número do CEP ou pelo endereço, como pode ser visto na documentação em https://viacep.com.br/. Exemplo de pesquisa com CEP em JSON ou XML: viacep.com.br/ ws/01001000/json/ ou viacep.com.br/ws/01001000/xml/. Figura 5 – JSON x XML. Fonte: Adaptado de viacep.com.br/. Vamos então começar a construção da nossa API, na qual utilizaremos apenas o retorno no formato JSON. Para facilitar, vamos aproveitar alguns módulos que já foram explicados em aulas anteriores, tais como, http, url e string. Vamos usar também um banco de dados de exemplo, que tem como estrutura o diagrama da Figura 6. Nele já temos dados inseridos em todas as tabelas, possibilitando uma melhor visualização dos resultados. Figura 6 – Estrutura BD. Fonte: Acervo pessoal. Uma nova pasta deve ser criada e renomeada a seu critério. Neste material a chamaremos de api-vendas. Dentro dela fazemos uma chamada a npm init para construção do arquivo package.json, como visto na aula 04. Responderemos as perguntas que forem solicitadas e o arquivo será preenchido automaticamente com o seguinte resultado. { “name”: “api-vendas”, “version”: “1.0.0”, “description”: “Criação de API para o banco de dados VENDAS”, “main”: “server.js”, “scripts”: { “test”: “echo \”Error: no test }, “author”: “Felipe Perez”, “license”: “ISC” }; Em seguida, é importante fazer a instalação dos módulos que serão necessários, fazendo a chamada ao npm para instalar os módulos de terceiros. npm install string --save npm install mysql --save npm install nodemon –save-dev Após a instalação de cada um dos módulos, as dependências são atualizadas então no arquivo package.json. { “name”: “api-vendas”, “version”: “1.0.0”, “description”: “Criação de API para o banco de dados VENDAS”, “main”: “server.js”, “scripts”: { “test”: “echo \”Error: no test }, “author”: “Felipe Perez”, “license”:“ISC”, “dependencies”: { “string”: “^3.3.3” }, “devDependencies”: { “nodemon”: “^1.19.1” } } aplicação api-vendas é o server.js, que deve ser criado na pasta raiz do aplicativo. No início desse arquivo iremos carregar todos os módulos que serão utilizados. Como a nossa API vai manipular os dados do MySQL, conectado corretamente. var con = mysql.createConnection({ host: “localhost”, 146 53 user: “root”, database: “vendas” }); con.connect(function(err) { if (err) throw err; console.log(“Conectado!”); }); A depender então da solicitação do usuário, a nossa API irá efetuar o que for pedido. Para isso, vamos criar um servidor HTTP que irá receber as informações através do request e rotas serão criadas para cada uma das funções do CRUD. Na URL para chamada, a API atenderá ao seguinte padrão: h t t p : / / l o c a l h o s t : 3 0 0 0 / t i p o / t a b e l a / c o l u n a / valor/?atributo1=valor1&atributo2=valor2 O pathname é responsável por informar ao servidor qual rota ele deve seguir dentro do servidor e a query receberá dados, quando necessário para inserção ou atualização no banco de dados. const server = http. createServer((request,response)=>{ var q = url.parse(request.url, true); console.log(q.pathname); console.log(q.query); }); server.listen(3000); em nossos testes, faremos uma chamada via nodemon para o arquivo server.js, que será atualizado sempre que houver uma acima iniciado e fazendo uma chamada ao servidor com a URL http://localhost:3000/get/cidade/?nome=Ponta Pora&estado=MS o servidor recebe então uma request. A partir da request.url o módulo url separa os dados contidos nela, e podem ser acessados diretamente como visto na Figura 7. Figura 7 – URL. Fonte: Acervo pessoal. No pathname os valores são divididos entre barras. Pode-se manipular essas informações utilizando a função .splitLeft(‘/’) do módulo string. Passamos por parâmetro qual a string que vai dividir os valores, no caso a barra, e ela nos retorna um array com cada um dos valores em uma posição. const server = http. createServer((request,response)=>{ var q = url.parse(request.url, true); var api = S(q.pathname). console.log(api); console.log(q.query); }); server.listen(3000); Após salvar o arquivo com as alterações acima, o nodemon percebe a atualização e reinicia o servidor. Quando fazemos novamente a solicitação http://localhost:3000/get/ cidade/?nome=Ponta Pora&estado=MS a forma de exibição do pathname já foi alterada, agora podemos acessar cada valor por uma posição do array criado. Figura 7 – splitLeft. Fonte: Acervo pessoal. podemos atribuir a algumas variáveis, o valor das posições relativas do array criado pelo pathname. Além disso, a função Object.entries() transforma cada par de chave e valor passado pela query como um array que pode ser acessado de sua posição. const server = http. createServer((request,response)=>{ var q = url.parse(request.url, true); var api = S(q.pathname). var tipo = api[1]; //get, set, new ou delete var tabela = api[2]; var coluna = var valor = api[4]; var query = Object.entries(q. query); }); server.listen(3000); Já sabemos o que o cliente quer, agora precisamos projetar as rotas que nosso servidor irá tomar dependendo do tipo que foi enviado pelo cliente. Cada rota representará uma ação do CRUD. Começaremos pela mais simples de se implementar. 147 Desenvolvimento Voltado a Web III 54 Read Para retornar o conteúdo de uma tabela para o cliente ele deverá, pelo menos, passar para a API o nome da tabela http://localhost:3000/get/cidade. Ele pode ainda criar uma condição passando mais dois parâmetros, fazendo com que a API retorne exatamente um dos registros http:// localhost:3000/get/cidade/codcid/3. Dentro do servidor é criado, então, um switch(tipo), que de acordo com a solicitação vai percorrer e retornar um dos var sql; response.setHeader(‘Content- switch(tipo){ sql = “SELECT * FROM “+tabela; sql += “+valor:””); console.log(sql); c o n . response.end(JSON. stringify(result)); response.end(); }); break; } Uma variável para que o comando SQL referente a essa ação é criada para que possa ser utilizada em todos os casos do switch. Em seguida, a resposta do tipo de conteúdo que o cliente irá receber é setado também para todos os casos, já que todos retornarão um JSON. O SELECT, então, é construído com o nome da tabela que o cliente enviou. E se o campo coluna também for passado pelo cliente, a cláusula WHERE é adicionada para Figura 8 – Select. Fonte: Acervo pessoal. Figura 9 – Select Where. Fonte: Acervo pessoal. Create do switch já criado. Para inserir um novo dado no banco de dados precisamos passar para a API o nome da tabela e os dados que serão inseridos http://localhost:3000/new/ cidade/?nomecid=Campinas&uf=SP. var colunas = “”; var valores = “”; var cont=0; query.forEach((each)=>{ colunas+=(cont>0)?”,”:””; valores+=(cont>0)?”,”:””; colunas+=each[0]; cont++; }); sql = “INSERT INTO “+tabela+”(“+colunas+”) VALUES (“+valores+”)”; r e s p o n s e . e n d ( J S O N . stringify(result)); response.end(); }); break; As variáveis valores e colunas são preenchidas de acordo com os parâmetros que forem enviados pela query, na url, pela função forEach() que percorre cada dupla de chave-valor criada anteriormente pelo Object.entries(). Com essas variáveis é construído o comando SQL, que irá inserir o dado no banco. O retorno serão as informações relativas à inserção em formato JSON, tais como linhas afetadas, id inserido, status do servidor. Figura 10 – Insert. Fonte: Acervo pessoal. 148 55 Update A função para atualizar os dados no banco deve conter todos os parâmetros utilizados até agora, o nome da tabela, o campo e valor que será utilizado para selecionar um dado Caso o campo e o valor não sejam informados, todos os registros da tabela terão seus valores atualizados. Para substituir somente o conteúdo da cidade cujo código é 3 http://localhost:3000/ set/cidade/codcid/3?nomecid=Campinas&uf=SP ou para substituir todos os estados por SP http://localhost:3000/set/ cidade/?uf=SP. var valores = “”; var cont=0; query.forEach((each)=>{ valores+=(cont>0)?”, “:””; valores+=each[0]+” = “; cont++; }); sql = “UPDATE “+tabela+” SET “+ valores; “+coluna+” = “+valor:””); r e s p o n s e . e n d ( J S O N . stringify(result)); response.end(); }); break; O preenchimento da variável valor se baseia no mesmo método do Insert. Como a estrutura do UPDATE é um pouco diferente do INSERT, algumas adaptações são feitas para poder funcionar. Além disso, a cláusula WHERE tem o mesmo funcionamento do SELECT com WHERE, a mesma dinâmica foi aproveitada aqui. Na Figura 11, a url chamada não passou um valor para a cláusula WHERE, afetando 19 linhas. Destas, 12 foram realmente atualizadas com os valores novos. Figura 11 – Update. Fonte: Acervo pessoal. Delete deletar registros no banco de dados, sempre tomando muitos cuidados, é claro, pois o registro, depois de deletado, não pode ser recuperado. Iremos implementar duas exclusões, uma quando é passado um parâmetro para comparação http:// localhost:3000/delete/cliente/codcli/3 e outro para deletar todas as instâncias que existirem no banco de dados http:// localhost:3000/delete/cliente, tomando muito cuidado com esse último, antes de testar faça um backup do seu banco de dados. sql = “DELETE FROM “+tabela; “+coluna+” = “+valor:””); console.log(sql); r e s p o n s e . e n d ( J S O N . stringify(result)); response.end(); }); break; Esse trecho possui a mesma função do caso get, simplesmente deleta tudo ou, caso alguma condição seja passada nos parâmetros, remove apenas os registros que atendam à condição. Deletando, retornará também um JSON com as informações sobre o que ocorreu no banco, como quantas linhas foram excluídas. Figura 12 – Delete. Fonte: Acervo pessoal. Retomando a aula1 – Usando o MySQL no Node.js Na primeira seção, a conexão com o MySQL foi estabelecida com o Node.js, e após isso foi possível executar querys nele. 2 – O que é CRUD? Em seguida, foi descrito o que é CRUD, que é o 149 Desenvolvimento Voltado a Web III 56 acrônimo de Create, Read, Update e Delete, que são as ações básicas que podem ser operadas no MySQL. 3 – Construindo uma API Na última seção foi explicado passo a passo de como construir uma API. LECHETA, R R. Node Essencial, Novatec, 2012. PEREIRA, C R. Aplicações web real-time com Node. js. Editora Casa do Código, 2014. PEREIRA, C R. Building APIs with Node. js. Apress, 2016. RUBENS, J. Primeiros passos com Node.js. Editora Casa do Código, 2017. Vale a pena ler COPES, F. In: The Node.js Handbook, 2019. Disponível em: <https://flaviocopes.com/page/ ebooks/>. Acesso em: 20 mai. 2019. DELBONO, E. In: Node.js Succinctly, 2016. Disponível em: <https://www.syncfusion.com/ebooks/ nodejs>. Acesso em: 20 mai. 2019. NETO, W. In: Construindo APIs testáveis com Node.js, 2018. Disponível em: < https://leanpub.com/ construindo-apis-testaveis-com-nodejs/>. Acesso em: 20 mai. 2019. MYSQL. In: Node.js MySQL, 2019. Disponível em: <https://www.w3schools.com/nodejs/nodejs_mysql. asp/>. Acesso em: 03 jun. 2019. CRUD. In: What is CRUD?, 2019. Disponível em: <https://www.codecademy.com/articles/what-is-crud>. Acesso em: 03 jun. 2019. PIRES, J. In: O que é API? REST e RESTful? Conheça as definições e diferenças, 2017. Disponível em: <https:// becode.com.br/o-que-e-api-rest-e-restful/>. Acesso em 03 jun. 2019. Vale a pena acessar Vale a pena Minhas anotações 150
Compartilhar