05 Jun 2022
En este post veremos cómo hacer que nuestra aplicación en Drogon interactúe con una base de datos Sqlite 3.
Para seguir los pasos de este post, descarga la versión 0.2.0 del repositorio de este tutorial.
Creamos nuestra nueva carpeta de trabajo partiendo desde docker/with-separated-images
:
cd docker
cp -r with-separated-images with-sqlite-3
Para nuestra primera prueba, este será el contenido sql con el que vamos a crear nuestra base de datos:
CREATE TABLE IF NOT EXISTS customers (
id VARCHAR(38) PRIMARY KEY,
name VARCHAR(255)
);
CREATE TABLE IF NOT EXISTS invoices (
invoice_number INT UNSIGNED PRIMARY KEY,
customer_id VARCHAR(38) NOT NULL,
total DECIMAL(15,2),
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
INSERT INTO customers (id, name) VALUES ('id1', "Antonio D. Bain");
INSERT INTO invoices (invoice_number, customer_id, total) VALUES (1, 'id1', 10.50);
INSERT INTO customers (id, name) VALUES ('id2', "Grace R. Shaw");
INSERT INTO invoices (invoice_number, customer_id, total) VALUES (2, 'id2', 34.54);
INSERT INTO customers (id, name) VALUES ('id3', "Emmett Savage");
INSERT INTO invoices (invoice_number, customer_id, total) VALUES (3, 'id3', 23.50);
Almacenamos este archivo con el nombre invoicer.sql
, dentro de una nueva carpeta docker/with-sqlite-3
. Para crear una base de datos sqlite 3 usaremos el siguiente comando en nuestra terminal: sqlite3 invoicer.db < invoicer.sql
. Al finalizar el comando, deberías tener un archivo invoicer.db
justo donde ejecutaste el comando mencionado.
En el archivo docker-compose.yml
vamos a incluir nuestra base de datos al container de la aplicación para tenerla disponible durante la ejecución:
version: "3.9"
services:
app:
build:
context: ../..
dockerfile: "${PWD}/Dockerfile"
volumes:
- "./invoicer.db:/app/invoicer.db"
ports:
- "8081:80"
Cuando nuestra aplicación se esté ejecutando, la base de datos, que es el archivo .db, estará disponible en la ruta /app/invoicer.db
.
Otro cambio que vamos a necesitar es instalar en nuestro container la librería de Sqlite. Como dicha librería es utilizada en tiempo de compilación y ejecución, la vamos a incorporar al archivo Dockerfile-common
, añadiendo libsqlite3-dev
a la lista de paquetes a instalar con apt-get
.
Para conectar nuestra aplicación a la base de datos invocaremos la función createDbClient a la lista de llamadas que hacemos para inicializar la aplicación en el archivo main.cc
:
drogon::app()
.addListener("0.0.0.0", port)
.setDocumentRoot("docroot")
.createDbClient("sqlite3", "", 3306, "", "", "", 5, "invoicer.db");
Se puede simplificar la inicialización de la aplicación usando un archivo de configuración json. En este tutorial elijo tenerlo explícitamente definido en el código, pero ambos enfoques son válidos. Usa el que más te guste.
El siguiente paso será añadir un nuevo controller. Como ya tenemos la versión 1 del listado de invoices (controller v1_invoices_list
), seguiremos esta línea y añadiremos la v2 de nuestra llamada para listar invoices:
cd controllers
drogon_ctl create controller v2::invoices::list
En el archivo controllers/v2_invoices_list.h
añadimos la definición del path de nuestro nuevo endpoint:
...
PATH_LIST_BEGIN
PATH_ADD("/v2/invoices", Get);
PATH_LIST_END
...
Luego, vamos al archivo controllers/v2_invoices_list.cc
donde añadiremos las líneas que permitirán que la aplicación obtenga información de la base de datos y genere el json de respuesta del endpoint:
auto clientPtr = drogon::app().getDbClient();
auto query = clientPtr->execSqlAsyncFuture("SELECT i.invoice_number, c.name, i.total FROM invoices i INNER JOIN customers c ON c.id = i.customer_id");
auto result = query.get();
Json::Value invoices(Json::arrayValue);
Json::Value invoice(Json::objectValue);
for (auto row : result) {
invoice["number"] = row["invoice_number"].as<std::string>();
invoice["customer"] = row["name"].as<std::string>();
invoice["total"] = row["total"].as<std::string>();
invoices.append(invoice);
}
auto resp=HttpResponse::newHttpJsonResponse(invoices);
resp->setStatusCode(k200OK);
resp->setContentTypeCode(CT_APPLICATION_JSON);
callback(resp);
Ahora que hemos codificado nuestro controller, reemplazamos el endpoint /v1/invoices
por /v2/invoices
en el archivo docroot/index.html
.
Estamos listos para compilar. Vamos a la carpeta docker/with-sqlite-3
y ejecutamos:
docker-compose build app
docker-compose up -d
Si todo ha salido bien, al cargar la url http://localhost:81
deberíamos ver los 3 registros que insertamos en la base de datos.
Espero hayan podido seguir el tutorial. Si surgió algún problema, dejame un comentario.
Les dejo el link al pull request con los cambios introducidos en este tutorial: Add interaction with sqlite 3.
¡Tu mensaje fue recibido! Una vez que sea aprobado, estará visible para los demás visitantes.
Cerrar