Está en la página 1de 91

ESCUELA DE GESTIÓN PÚBLICA PLURINACIONAL

JAVA DATABASE INTERFACE 3 (JDBI3) APLICACIÓN


PRÁCTICA UTILIZANDO POSTGRESQL Y JERSEY
RESTFUL WEB SERVICES

Vladimir Cabrera Arandia


Juan Gonzalo Rodriguez Arce

La Paz, 2020
JAVA DATABASE INTERFACE 3 (JDBI3) APLICACIÓN
PRÁCTICA UTILIZANDO POSTGRESQL Y JERSEY
RESTFUL WEB SERVICES

Vladimir Cabrera Arandia


Juan Gonzalo Rodriguez Arce

La Paz, 2020
¡A ti, querido lector! Por interesarte en el mundo de la Tecnología
Informática.
AGRADECIMIENTOS

Queremos dar las gracias a todas las personas que hicieron posible la
presente monografía “Java Database Interface 3 aplicación práctica
utilizando PostgreSQL y Jersey Restful Web Services”. Primeramente,
debemos agradecer a la: Escuela de Gestión Pública Plurinacional (EGPP),
por formar y capacitar de forma continua a la sociedad boliviana. De la
misma manera, agradecer a: Ing. José Marcelo Rocabado Torrez, Inga.
Maritza Condori Quispe, Inga Alejandra Fuentes, por la labor que
desempeñan dentro la EGPP; desde la coordinación hasta elaboración
temática de cada uno de los cursos que imparten.
Vladimir y Juan Gonzalo

A nivel personal quiero dar un agradecimiento especial a todos los


compañeros del curso que a pesar de que no les puede conocer
personalmente, pudimos compartir diferentes puntos vista en cada una de las
clases, también agradecer a los canales de YouTube que difunden material
acerca de la ciencia de la computación. ¡muchas gracias!
Vladimir Cabrera Arandia

Agradezco a Dios por guiarme en mi camino y por permitirme concluir con mi


objetivo, a mis padres quienes son mi motor y mi mayor inspiración, que, a
través de su amor, paciencia, buenos valores, ayudan a trazar mi camino.
A toda mi familia por ser el apoyo incondicional en mi vida, que, con su amor
y respaldo, me ayudan alcanzar mis objetivos.
Juan Gonzalo Rodriguez Arce
ÍNDICE DE CONTENIDO

CAPÍTULO I __________________________________________________ 1

INTRODUCCIÓN ________________________________________________ 1

1.1. PROBLEMA ______________________________________________ 2


1.1.1. Subproblemas ________________________________________________2
1.1.2. Causas del Problema __________________________________________2

1.2. OBJETO DE ESTUDIO ______________________________________ 3

1.3. CAMPO DE ACCIÓN _______________________________________ 3

1.4. OBJETIVOS ______________________________________________ 3


1.4.1. Objetivo General ______________________________________________3
1.4.2. Objetivos Específicos __________________________________________3

1.5. ALCANCE ________________________________________________ 4

1.6. FACTIBILIDAD ____________________________________________ 4


1.6.1. Factibilidad Operativa ______________________________________________4
1.6.2. Factibilidad Económica _____________________________________________5

1.7. JUSTIFICACIÓN ___________________________________________ 5

1.8. BENEFICIOS ________________________________________________ 6

CAPÍTULO II: DIAGNÓSTICO DE LA SITUACIÓN ACTUAL DEL ACCESO


A LOS DATOS DE UNA BASE DE DATOS DESDE UN LENGUAJE DE
PROGRAMACIÓN _____________________________________________ 7

2.1. ANTECEDENTES DEL ACCESO A DATOS ________________________ 7

2.2. ACCESO A DATOS DESDE UN LENGUAJE DE PROGRAMACIÓN_____ 8

2.3. DIAGNÓSTICO DEL OBJETO DE ESTUDIO ______________________ 10

CAPÍTULO III: MARCO TEÓRICO DE JAVA DATABASE INTERFACE 3


(JDBI3) APLICACIÓN PRÁCTICA UTILIZANDO POSTGRESQL Y JERSEY
WEB SERVICES _____________________________________________ 15

i
3.1. JAVA DATABASE INTERFACE (JDBI) ________________________ 15
3.1.1. Jdbi 3 ______________________________________________________16
3.1.1.1. API Fluida __________________________________________________17
3.1.1.2. API Declarativa ______________________________________________18
3.1.2. Núcleo API _________________________________________________20
3.1.2.1. Handle ___________________________________________________21
3.1.2.2. Argumentos _______________________________________________22
3.1.2.2.1. Argumentos Posicionales _________________________________22
3.1.2.2.2. Argumentos Nombrados __________________________________22
3.1.2.2.3. Tipos de argumentos admitidos ____________________________23
3.1.2.2.4. Argumentos Vinculantes (Binding) __________________________24
3.1.2.2.5. Argumentos Personalizados _______________________________ 26

3.2. SISTEMA ADMINISTRADOR DE BASE DE DATOS ______________ 30


3.2.1. PostgreSQL _________________________________________________30

3.3. SERVICIOS WEB (WEB SERVICES) __________________________ 32


3.3.1. Jersey RESTful Web Services __________________________________33

3.4. ÍTEM CUENTAS POR COBRAR: PLAN DE CUENTAS CONTABLE _ 35

CAPÍTULO IV: APLICACIÓN PRÁCTICA DESARROLLO DEL SERVICIO


WEB “DENARIUS” ___________________________________________ 37

4.1. CREACIÓN DE LA BASE DE DATOS ___________________________ 37

4.2. DESARROLLO DEL SERVICIO WEB ____________________________ 41


4.2.1. Archivo pom.xml _________________________________________________42
4.2.2. Archivo web.xml _________________________________________________44
4.2.3. Db.properties ___________________________________________________46
4.2.4. ConectorBD ____________________________________________________47
4.2.5. Data Transfer Objects_____________________________________________48
4.2.5.1. Articulos.java ________________________________________________48
4.2.5.2. Deudores.java _______________________________________________50
4.2.5.3. Movimientos.java _____________________________________________51
4.2.5.4. Saldos.java _________________________________________________53
4.2.5.5. Tipo_usuarios.java ___________________________________________54
4.2.5.6. Usuarios.java________________________________________________55
4.2.6. Data Access Objects _____________________________________________56

ii
4.2.6.1. ArticulosDAO.java ____________________________________________56
4.2.6.2. MovimentosDAO.java _________________________________________57
4.2.6.3. SaldoDAO.java ______________________________________________58
4.2.6.4. Tipo_usuariosDAO.java________________________________________59
4.2.7. Servicios Rest ___________________________________________________60
4.2.7.1. ServicioArtículos.java _________________________________________60
4.2.7.2. Servicio Movimientos.java ______________________________________63
4.2.7.3. Servicio Saldos.java __________________________________________66
4.2.7.4. Servicio Tipo Usuario.java ______________________________________67
4.2.7.5. Servicio Deudores.java ________________________________________69
4.2.7.6. Servicio Usuarios.java _________________________________________72

VENTAJAS Y DESVENTAJAS DE UTILIZAR JDBI__________________ 75

VENTAJAS ____________________________________________________ 75

DESVENTAJAS ________________________________________________ 76

CONCLUSIONES _____________________________________________ 77

RECOMENDACIONES ________________________________________ 78

BIBLIOGRAFÍA ______________________________________________ 79

GLOSARIO DE TÉRMINOS_____________________________________ 81

DATOS PERSONALES DE LOS INTEGRANTES ___________________ 82

iii
ÍNDICE DE FIGURAS

Figura 1: Mapeo Objeto-Relacional........................................................................................10


Figura 2 Relación OneToOne ................................................................................................12
Figura 3 Posible solución para conflicto de persistencia OneToOne .....................................12
Figura 4 Excepción al recuperar colección de Carga Diferida ................................................13
Figura 5 Solución (1) a: Excepción de Carga Diferida mediante artificio ...............................13
Figura 6 Solución (2) a: Excepción de Carga Diferida ...........................................................14
Figura 7 Java Database Interface 3 .......................................................................................15
Figura 8 Arquitectura Jdbi ......................................................................................................16
Figura 9 API Fluida ................................................................................................................18
Figura 10 API Declarativa ......................................................................................................19
Figura 12 Cuentas por Cobrar................................................................................................35
Figura 13 Registro de Cuentas por cobrar .............................................................................36
Figura 14 Modelo Entidad Relación “denarius” ......................................................................37
Figura 15 Proyecto Web con Maven en Apache Netbeans 11 ...............................................41
Figura 16 Elección de Servidor Web y Versión de Java a utilizar ..........................................41
Figura 17 Estructura del Proyecto Maven: “DenariusRestJdbi” ..............................................42
Figura 18 Localización del Archivo: “web.xml”, proyecto Maven ............................................44
Figura 19 Localización de Paquetes ......................................................................................45
Figura 20 Archivo: “db.properties” ..........................................................................................46
Figura 21 Localización: Clase “dbProperties.java” .................................................................46
Figura 22 Localización: Clase “conectorBD.java” ...................................................................47
Figura 23 Localización: Clases DTO ......................................................................................48
Figura 24 Localización de: Interfaces DAO ............................................................................56
Figura 25 Localización del Servicio REST: “ServicioArticulos.java” .......................................60
Figura 26 Localización del Servicio REST: “ServicioMovimientos.java” .................................63
Figura 27 Localización del Servicio REST: “ServicioSaldos.java” ..........................................66
Figura 28 Localización del Servicio REST: “ServicioTipo_usuario.java” ................................67
Figura 29 Localización del Servicio REST: “ServicioDeudores.java” .....................................69
Figura 30: Localización del Servicio REST: “ServicioUsuarios.java” ......................................72

iv
RESUMEN

La presente monografía: “Java Database Interface 3 (Jdbi3) Aplicación


Práctica Utilizando PostgreSQL Y Jersey Restful Web Services” fue
realizada para dar a conocer las bondades de la librería Jdbi a través de un
ejemplo práctico.

Para lograr este fin se realizó una recopilación de información acerca del:
acceso a los datos de una base de datos, desde lenguajes de programación.
Describiendo de manera cronológica los eventos más relevantes, ocurridos
hasta a la actualidad.

De igual forma, la monografía, describe las particularidades que presenta: la


persistencia de datos, que es una de las formas actuales de acceder a los
datos, desde los lenguajes de programación.

También describe los conceptos teóricos básicos acerca de: Sistemas de


Gestión de Base de Datos, Servicios Web y Java Database Interface (Jdbi),
explicando este último de forma detallada.

Finalmente se desarrolla el servicio web: “DenariusRestJdi” para que, de


manera práctica se consolide el conocimiento del lector.
CAPÍTULO I

INTRODUCCIÓN

La utilización de las bases de datos relacionales condujo a la proliferación de


acceso a los datos almacenados en estas, que funcionaban mediante un
procesador de comandos; sin embargo, los desarrolladores querían utilizar
SQL dentro de programas escritos en lenguajes de programación, esto llevó
al concepto de SQL Incrustado (Embedded SQL) y posteriormente a la
creación de ODBC (Open Database Connectivity) 1.0 que se convertiría en la
interfaz base para el acceso a datos multiplataforma (cross-platform data
access). Sun Microsystems utilizó ODBC como base para su propio estándar
abierto, Java Database Connectivity (JDBC) (Wikipedia contributors, 2020).

Malcolm Phillip Atkinson, investigó acerca de: bases de datos, la persistencia


y sus aplicaciones, logrando acuñar el concepto, "Persistencia ortogonal"
(Danielsen, 1999). Como consecuencia en 2006 se lanzaría la especificación
JPA 1.0 (Java Persistence API) (Wikipedia contributors, 2020).

Sin embargo, JPA tiene ciertas deficiencias. Por esa razón ingenieros de
software entre ellos Brian McCallister, desarrollaron: “Java Database
Interface (Jdbi)”, una librería (biblioteca) Java para: trabajar el acceso a las
bases de datos directamente sobre el DBMS, utilizando las bondades de
Java 8 y manteniendo el mismo nivel de detalle que JDBC.

Para aplicar de manera práctica lo descrito en los parágrafos anteriores se


desarrolló el Servicio Web, “denarius”; utilizado para llevar el registro de la
Cuentas por Cobrar de una Empresa.

1
1.1. PROBLEMA

La tecnología utilizada para la recuperación de datos de una Base de Datos


en los lenguajes de programación actualmente tiene ciertas deficiencias, a
pesar de que se establecieron estándares para solucionar estos problemas a
través de la persistencia de datos.

1.1.1. Subproblemas
• La información de los datos que se encuentran en las Bases de
Datos no siempre se actualiza de manera correcta cuando se
utiliza persistencia de datos.
• A pesar de utilizar estrategias de recuperación de datos
(Lazy/Eager Loading) los lenguajes de programación en ciertas
circunstancias muestran datos diferentes a los del Gestor de Base
de Datos que se emplea para desarrollar aplicaciones informáticas.
• Desconocimiento de los artificios, por parte de los desarrolladores,
que se deben utilizar para sincronizar los datos visualizados por el
lenguaje de programación con los datos registrados en las bases
de datos.
• Conocimiento parcial del estándar JPA y su utilización de este en
las estructuras de trabajo (Framework) que siguen este estándar,
por parte de los desarrolladores.

1.1.2. Causas del Problema


• Necesidad de los desarrolladores de utilizar un Gestor de Base de
Datos en el desarrollo de sus Aplicaciones.
• Existencia de varios tipos de Gestores de Bases de Datos en el
mercado.

2
• Necesidad de no ser dependiente de un Gestor de Base de Datos en
específico.

1.2. OBJETO DE ESTUDIO

La interfaz Java Database (Jdbi) 3 utilizando PostgreSQL y Jersey Restful


Web Services.

1.3. CAMPO DE ACCIÓN

Demostración de las bondades de Java Database Interface 3, utilizando


PostgreSQL como Gestor de Base de Datos y Jersey Restful Web Services
para visualizar los resultados de los registros del seguimiento a: Las Cuentas
por Cobrar de una empresa.

1.4. OBJETIVOS

1.4.1. Objetivo General


Demostrar las características de Java Database Interface 3, a través de la
exposición de Servicios Web, para registrar y llevar el seguimiento de las
Cuentas por Cobrar de una empresa.

1.4.2. Objetivos Específicos


Para cumplir el objetivo general se deberá cumplir los siguientes objetivos
específicos:

3
• Realizar un estudio y recopilación de información acerca de la librería
o biblioteca Jdbi.
• Realizar un diseño de Base de Datos desarrollada en PostgreSQL
para poder plasmar la utilización de Jdbi.
• Desarrollar un servicio web utilizando Jersey Restful Web Services.
• Aplicar la utilización de Jdbi, PostgreSQL y Jersey Restful Web
Services para desarrollar un Servicio Web que lleve los registros del
Ítem Cuentas por Cobrar Clientes del Plan de Cuentas de Contabilidad
de una empresa.

1.5. ALCANCE

La presente monografía ayudará a despertar en el lector la posibilidad de:


utilizar una potente librería (biblioteca) desarrollada en Java como forma de
acceso a los datos de los diferentes gestores de bases de datos, sin
necesidad de utilizar las características que tienen las estructuras de trabajo
actuales basadas en el estándar de persistencia de datos JPA.

1.6. FACTIBILIDAD

1.6.1. Factibilidad Operativa


Los integrantes de la presente monografía se encuentran con motivación
para realizar un estudio acerca de alternativas que tiene el mercado para
desarrollar aplicaciones con acceso a base de datos que no dependan
exclusivamente del estándar de persistencia de datos JPA.

4
Además, se cuenta con la información que exhibe la internet a través de
páginas web, imágenes videos, blogs, comunidades, libros en línea, etc.;
para recopilar la información necesaria.

1.6.2. Factibilidad Económica


Todos los componentes informáticos utilizados para el desarrollo de la
exposición del Servicio Web de Cuentas por Cobrar desde ahora en adelante
llamado “denarius”, estarán desarrollados con herramientas de software libre,
las cuales no implican adquirir permisos corporativos exclusivos.

1.7. JUSTIFICACIÓN

La elaboración de la monografía referente a: “Java Database Interface 3


aplicación práctica utilizando PostgreSQL y Jersey Restful Web
Services”, permitirá a los lectores conocer de manera concisa las ventajas
de emplear Jdbi en la resolución y desarrollo de sistemas informáticos a
través de un ejemplo que abordará conceptos básicos de Base de Datos,
Servicios Web, manejo y seguimiento del ítem Cuentas por Cobrar del Plan
de cuentas contables de cualquier empresa.

Los integrantes de la presente monografía, observaron la necesidad de


mostrar a los lectores una alternativa diferente al empleo de persistencia de
datos como mecanismo de recuperación y acceso de datos desde el lenguaje
de programación Java.

5
1.8. BENEFICIOS

Los beneficios que se lograrán obtener en la presente monografía son:

• Adquisición de nuevo conocimiento por parte del lector.

• Dar a conocer una nueva alternativa que se tiene para el acceso a los
datos de una Base de datos desde el lenguaje de programación Java.

• Demostración práctica a través del desarrollo de un Servicio Web, que


sirve para llevar el registro y seguimiento de las Cuentas por Cobrar
de una empresa, la utilización de Jdbi y Servicios Web.

6
CAPÍTULO II: DIAGNÓSTICO DE LA SITUACIÓN
ACTUAL DEL ACCESO A LOS DATOS DE UNA BASE
DE DATOS DESDE UN LENGUAJE DE
PROGRAMACIÓN

Es pertinente describir en este segundo capítulo: la situación del acceso a los


datos de una base de datos desde un lenguaje de programación,
identificando los mecanismos que emplean los desarrolladores para acceder
a estos.

2.1. ANTECEDENTES DEL ACCESO A DATOS

Con el uso creciente de las computadoras por parte del ser humano, nació la
necesidad de almacenar los datos ingresados a estas, de forma duradera, en
algún lugar; esto ocasionó que en 1964 naciera el primer sistema de gestión
de base de datos (DBMS - Database Management System) llamado
“Almacén de Datos Integrado” (IDS Integrated Data Store) desarrollado en
General Electric, basado en el modelo de datos de red de Charles William
Bachman.

A finales de la década de los 60, IBM (International Business Machine) y


North American Aviation, más tarde Rockwell International, desarrollaron el
“Sistema de Gestión de la Información” (IMS - Information Management
System) con un modelo jerárquico (modelo de datos organizados en forma
de un árbol) considerado como el primer DBMS.

7
En 1970, Edgar Frank. Codd publicó un artículo con un enfoque diferente,
donde los datos en una base de datos podrían representarse con una
estructura tabular (tablas con columnas y filas, que él denominó relaciones) y
que podían acceder a estas relaciones utilizando un lenguaje de alto nivel, en
lugar de escribir algoritmos para acceder a los datos, esto dio inicio a la
creación de sistemas de gestión de bases de datos relacionales (RDBMS –
Relational DataBase Management System).

A medida que los DBMS evolucionaron creando estándares, también lo


hicieron los lenguajes de programación estableciendo paradigmas.

En 1991 Sun’s Green Team empezó el desarrollo de un nuevo lenguaje de


programación basado en C++ al que le llamaría “Oak” para después ser
distribuido de forma gratuita bajo el nombre de “Java” (Danielsen, 1999)

2.2. ACCESO A DATOS DESDE UN LENGUAJE DE


PROGRAMACIÓN

El uso de sistemas de gestión de bases datos y la forma rudimentaria que


tenían estos de mostrar los datos a los usuarios, despertó en los
desarrolladores el interés de utilizar el leguaje SQL en los lenguajes de
programación (Fortran o C). Esto llevó al concepto de SQL incrustado
(Embedded SQL) que permitió utilizar el lenguaje SQL de los DBMS en
lenguajes de programación a través de librerías (bibliotecas) que convertían
las sentencias del código del lenguaje de programación en declaraciones
SQL y de forma inversa los resultados de esas declaraciones en formatos de
datos que los lenguajes de programación entendían.

8
De la misma manera que los DBMS y los lenguajes de programación, el
concepto de utilizar SQL en los lenguajes de programación fue
evolucionando y en septiembre de 1992 Microsoft y Simba Technologies
lanzan ODBC (Open Database Connectivity) 1.0 que se convertiría en la
interfaz base para el acceso a datos multiplataforma (cross-platform data
access), más tarde Sun Microsystems utilizó ODBC como base para su
propio estándar abierto, Java Database Connectivity (Wikipedia contributors,
2020).

Por otra parte, Malcolm Phillip Atkinson, en la década de los 70 trabajaba en


la investigación de bases de datos, la persistencia y sus aplicaciones,
logrando acuñar el concepto, "Persistencia ortogonal", que plasmaría en el
proyecto PJama que es una versión ortogonalmente persistente de Java que
sigue los siguientes principios (Danielsen, 1999):

Principio de la independencia de la persistencia, refiere que un


programa es independiente de la longevidad de los datos que
manipula. Los programas tienen el mismo aspecto si manipulan datos
a corto o largo plazo.

Principio de la ortogonalidad del tipo de datos, refiere que todos


los objetos de datos se les debe permitir el rango completo de
persistencia independientemente de su tipo. No hay casos especiales
donde no se permita que los objetos sean duraderos o que no sean
transitorios.

Principio de identificación de persistencia, refiere que: la elección


de cómo identificar y proporcionar objetos persistentes es ortogonal al
universo del discurso del sistema. El mecanismo para identificar
objetos persistentes no está relacionado con el sistema de tipos.

9
Dados los conceptos previos se puede decir que en la última década se
popularizó el uso de la persistencia de datos como forma de acceder a los
diferentes DBMS; sin embargo, existen ciertas observaciones que se
presentan al utilizar esta forma de acceso a las bases de datos por parte de
los lenguajes de programación.

2.3. DIAGNÓSTICO DEL OBJETO DE ESTUDIO

Es indudable que al utilizar la persistencia de datos (JPA – Java Persistence


API) se reduce la escritura de códigos relacionales para la gestión de
objetos; sin embargo, la persistencia de datos como forma de acceder a los
datos de una base de datos presenta las siguientes particularidades:

AL emplear el Mapeo Objeto-Relacional (ORM - Object Relational Mapping)


se puede decir que este cuenta con tres fases (Tutorials Point, s.f.)

Figura 1: Mapeo Objeto-Relacional

10
1. Fase de datos del objeto, que contiene las clases POJO (Plain old
Java object), interfaces de servicio DAO (Data Access Object) y
clases.

2. Fase de mapeo o persistencia, que contiene al proveedor JPA; el


archivo mapeado (ORM.xml); JPA Loader que trabaja como una
memoria temporal, cache, la cual recupera los datos relacionales y
finalmente Object Grid que también es una ubicación temporal donde
se efectúan primero todas las consultas realizadas a la base de datos
y solo después de realizar la confirmación (commit) afecta a los datos
reales de la base de datos.

3. Fase de datos relacionales, que contiene los datos relacionales que


solo son afectados cuando se realizan las confirmaciones (commit),
hasta entonces son almacenados temporalmente en los Object Grid.

Como la persistencia se realiza en tres fases, se observa que en la fase


número dos (Fase de mapeo o persistencia) se debe volver a realizar las
relaciones que ya se trabajaron en una primera instancia al definir la base de
datos en el gestor de base de datos.

Se debe tener cuidado con el tipo de relaciones que se realiza ya que deben
estar acordes a las relaciones establecidas en el gestor de base de datos.

También se debe tener cuidado de elegir las estrategias de recuperación de


los datos al momento de utilizar persistencia ya que cada una de ellas tiene
sus particularidades. Por ejemplo, la estrategia: “Carga Diferida” (Lazy
loading) recupera todos los objetos dependientes solo cuando se utilizan,
evitando la precarga de los objetos que no podrían llegar a utilizarse; por otro

11
lado, tenemos la estrategia de “Carga Previa” (Eager Loading) que recupera
todos los objetos a un principio, aunque no se los necesite.

La mayoría de las estructuras de trabajo (frameworks) de persistencia tienen


configuradas la Carga Diferida por defecto; pero esta también trae ciertos
inconvenientes ya que, la fase de mapeo o persistencia, no almacena los
datos en la base de datos hasta el momento de la confirmación (commit) de
las transacciones. Por ejemplo, en una relación OneToOne las transacciones
se deben realizar en ciclos de vida diferentes, para que pueda haber una
coherencia al momento de persistir los datos.

Figura 2 Relación OneToOne

Figura 3 Posible solución para conflicto de persistencia OneToOne

12
Otro ejemplo puede ocurrir cuando se utiliza relaciones OneToMany o
ManyToOne ya que la persistencia de datos utiliza por defecto la
configuración de Carga Diferida (Lazy Loading), por consiguiente, la
recuperación de datos no será efectiva hasta que realicemos la petición
explícitamente, ya que así ahorramos recursos; en el caso de OneToMany la
tabla correspondiente a (One) no podrá obtener los datos de la tabla muchos
(Many) hasta que se acceda a esta última.

Figura 4 Excepción al recuperar colección de Carga Diferida

Para solucionar la excepción se puede tomar dos caminos: a) realizar un


artificio llamando a la entidad. en el ejemplo de abajo: libros.size().

Figura 5 Solución (1) a: Excepción de Carga Diferida mediante artificio

13
b) Declarar la colección como Carga Previa y así obtendríamos los datos en
el momento de la petición

Figura 6 Solución (2) a: Excepción de Carga Diferida

La consecuencia de utilizar Carga Previa (Eager Loading) es que, si no se


utilizaran los datos recuperados, estos estarían perjudicando el rendimiento
total de la aplicación, porque fueron cargados inútilmente (MakiGAS93,
2016).

Como se puede observar estos son algunos de los inconvenientes que tiene
el acceso a datos utilizando la persistencia, por esta razón un grupo de
Ingenieros de Software entre ellos Brian McCallister, desarrollaron una
librería (biblioteca) para: facilitar la fase de la persistencia de datos y trabajar
directamente sobre el DBMS; nombrándola Java Database Interface (Jdbi).

14
CAPÍTULO III: MARCO TEÓRICO DE JAVA
DATABASE INTERFACE 3 (JDBI3) APLICACIÓN
PRÁCTICA UTILIZANDO POSTGRESQL Y JERSEY
WEB SERVICES

El presente capítulo hace un análisis crítico de los fundamentos teóricos en


los cuales se apoya, “Java Database Interface (Jdbi) Aplicación Práctica
utilizando PostgreSQL y Jersey Web Services” describiendo los conceptos
más importantes que se utilizaron para desarrollo de esta monografía.

3.1. JAVA DATABASE INTERFACE (JDBI)


Jdbi es una librería SQL (Lenguaje Estructurado de Consultas) para el
lenguaje de programación JAVA, tiene una licencia Apache 2 e intenta
exponer el acceso a las bases de datos relacionales en Java de forma
idiomática (peculiar del lenguaje Java), utilizando colecciones, bean (modelo
de componentes) y otros, mientras mantiene el mismo nivel de detalle que
JDBC (Conectividad a Base de Datos Java) (Jdbi, 2020).

Figura 7 Java Database Interface 3

15
3.1.1. Jdbi 3
La versión número 3 de Jdbi tiene mejoras en el diseño, implementación y
soporte para complementos modulares, además utiliza las mejoras de Java
8, está construido sobre JDBC, mejorando y proporcionando una interfaz de
base datos Java más natural. A diferencia de un ORM (Mapeo de Objetos
Relacionales), Jdbi es más ligero y permite el mapeo entre relaciones y
objetos según las necesidades del desarrollo de la aplicación.

Figura 8 Arquitectura Jdbi

Jdbi puede ser utilizado empleando dos tipos de estilos:


a) API fluida.
b) API declarativa.

16
3.1.1.1. API Fluida

El núcleo de Jdbi proporciona una interfaz fluida e imperativa que es: la


ejecución de instrucciones una tras otra de manera secuencial.

Jdbi jdbi = Jdbi.create(


"jdbc:postgresql://localhost:5432/nombreBD",
"usuarioBD",
"contraseñaUsuarioBD"
);

List<Usuarios> usuarios = jdbi.withHandle(handle -> {


handle.execute("CREATE TABLE usuarios (id INTEGER PRIMARY KEY, nombre VARCHAR)");

// Parámetros posicionales en línea


handle.execute("INSERT INTO usuarios(id, nombre) VALUES (?, ?)", 0, "Alice");

// Parámetros posicionales
handle.createUpdate("INSERT INTO usuarios(id, nombre) VALUES (?, ?)")
.bind(0, 1) // Índices de parámetros base-0
.bind(1, "Bob")
.execute();

// Parametros nombrados
handle.createUpdate("INSERT INTO usuarios(id, nombre) VALUES (:id, :nombre)")
.bind("id", 2)
.bind("nombre", "Clarice")
.execute();

// Named parameters from bean properties


handle.createUpdate("INSERT INTO usuarios(id, nombre) VALUES (:id, :nombre)")
.bindBean(new User(3, "David"))
.execute();

// Easy mapping to any type


return handle.createQuery("SELECT * FROM usuarios ORDER BY nombre")
.mapToBean(User.class)
.list();
});

assertThat(users).containsExactly(
new User(0, "Alice"),
new User(1, "Bob"),
new User(2, "Clarice"),
new User(3, "David"));

17
Figura 9 API Fluida

3.1.1.2. API Declarativa

La extensión SQL Object (Objeto SQL) que se encuentra en el núcleo de Jdbi


provee una interfaz declarativa, que son instrucciones que se aplican para
lograr un resultado, las cuales indican a Jdbi qué consultas SQL ejecutar y de
qué manera mostrar los resultados de estas en una interfaz.

// Define la interfaz declarativa


public interface UsuarioDao {
@SqlUpdate("CREATE TABLE usuario (id INTEGER PRIMARY KEY, nombre VARCHAR)")
void crearTabla();

@SqlUpdate("INSERT INTO usuario(id, nombre) VALUES (?, ?)")


void insercionPosicional(int id, String nombre);

@SqlUpdate("INSERT INTO usuario(id, nombre) VALUES (:id, :nombre)")


void insercionNombrada(@Bind("id") int id, @Bind("nombre") String nombre);

@SqlUpdate("INSERT INTO usuario(id, nombre) VALUES (:id, :nombre)")


void insercionBean(@BindBean Usuario usuario);

@SqlQuery("SELECT * FROM usuario ORDER BY name")


@RegisterBeanMapper(Usuario.class)
List<Usuario> listaUsuario();
}
Jdbi jdbi = Jdbi.create( "jdbc:postgresql://localhost:5432/nombreBD",
"usuarioBD",
"contraseñaUsuarioBD"
);
jdbi.installPlugin(new SqlObjectPlugin());

// Jdbi implementa interfaz basada en anotaciones

18
List<Usuario> nombresUsuario = jdbi.withExtension(UsuarioDao.class, dao -> {
dao.crearTabla();

dao.insercionPosicional(0, "Alice");
dao.insercionPosicional(1, "Bob");
dao.insercionNombrada(2, "Clarice");
dao.insercionBean(new User(3, "David"));

return dao.listaUsuario();
});

assertThat(nombreUsuario).containsExactly(
new Usuarios(0, "Alice"),
new Usuarios(1, "Bob"),
new U(2, "Clarice"),
new User(3, "David"));

Figura 10 API Declarativa

Jdbi está conformado por complementos(plug-in) flexibles que facilitan la


interacción y soporte a diferentes librerías (bibliotecas) como son: Guava,
JodaTime, Spring, Vavr o bases de datos: H2, Oracle, PostgreSQL.

Jdbi no es un ORM, no tiene una sesión para guardar temporalmente los


datos, cache. Tampoco realiza una sesión en vista (Open Session in View), a

19
cambio, proporciona una asignación directa entre SQL y estructuras de datos
tabulares simples, ejecutando los comandos que se le indica solamente.

Jdbi es fácil de incluir en un proyecto Java mediante pocas dependencias y


JARs distribuidos en la Maven Central. Ejemplo de inclusión en POM
(Modelo de Objeto del Proyecto):

<dependencies>
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-core</artifactId>
</dependency>
</dependencies>

3.1.2. Núcleo API


La clase Jdbi es el principal punto de entrada de la librería (biblioteca), cada
instancia Jdbi envuelve una fuente de datos (Data Source JDBC). También
es un repositorio de configuración para la sesión de base de datos.

Las formas de crear una instancia Jdbi son:

// Base de datos PostgreSQL


Jdbi jdbi = Jdbi.create("jdbc:postgresql://localhost:5432/nombreBD",
"usuarioBD",
"contraseñaUsuarioBD ");

Si se cuenta con un objeto de fuente de Datos, DataSource

DataSource ds = …
Jdbi jdbi = Jdbi.create(ds);

Las instancias Jdbi son seguras (thread-safe) y no poseen ningún recurso de


Base de Datos.

20
3.1.2.1. Handle
Los manejadores (Handles) representan una conexión de Base de Datos
activa, se utiliza para preparar ejecutar y administrar transacciones SQL en la
base de datos, proporcionan acceso al tipo de estilo API fluida, las cuales
pueden vincular argumentos, ejecutar sentencias y mapear (proyectar) los
resultados en Java.

Handle hereda la configuración Jdbi en el momento que se crea; las formas


de obtener una instancia Handle en tiempo de ejecución son:

a) Si la operación retorna un resultado, utilizar jdbi.withHandle():

List<String> names = jdbi.withHandle(handle ->


handle.createQuery("SELECT nombre from contactos")
.mapTo(String.class)
.list());
assertThat(names).contains("Alice", "Bob");

b) Si la operación no necesita retornar un resultado, utilice


jdbi.useHandle (HandleCosumer):

jdbi.useHandle(handle -> {
handle.execute("create table contactos (id int primary key, name varchar(100))");
handle.execute("insert into contactos (id, nombre) values (?, ?)", 1, "Alice");
handle.execute("insert into contactos (id, nombre) values (?, ?)", 2, "Bob");
});

Alternativamente, si desea administrar el ciclo de vida del identificador


(handle) utilice jdbi.open()

try (Handle handle = jdbi.open()) {


handle.execute("insert into contactos (id, nombre) values (?, ?)", 3, "Chuck");
}

21
3.1.2.2. Argumentos

Los argumentos son las representaciones Jdbi de los parámetros de la


declaración JDBC (el signo interrogación “?” en: SELECT * FROM tabla
WHERE columna = ?).

Para establecer un parámetro (?) en JDBC debe escribir la siguiente


sentencia: ps.setString(1, “Baz”); en cambio en Jdbi buscará “Baz” en todas
las instancias ArgumentFactory registradas hasta encontrar una que
convierta la cadena en un argumento. El argumento es responsable de
configurar la cadena exactamente como lo hace setString.

3.1.2.2.1. Argumentos Posicionales

Cuando una instrucción SQL utiliza los signos (tokens) de: “?”, Jdbi puede
enlazar los valores a los parámetros en el índice correspondiente (0, posición
inicial).

handle.createUpdate("insert into contactos (id, nombre) values (?, ?)")


.bind(0, 3)
.bind(1, "Chuck")
.execute();

String name = handle.createQuery("select nombre from contactos where id = ?")


.bind(0, 3)
.mapTo(String.class)
.one();

3.1.2.2.2. Argumentos Nombrados

Cuando una instrucción SQL utiliza los signos “:”, como en “: name”, Jdbi
puede enlazar parámetros por nombre:

22
handle.createUpdate("insert into contactos (id, nombre) values (:id, :name)")
.bind("id", 3)
.bind("nombre", "Chuck")
.execute();

String name = handle.createQuery("select nombre from contactos where id = :id")


.bind("id", 3)
.mapTo(String.class)
.one();

3.1.2.2.3. Tipos de argumentos admitidos

Adicionalmente, Jdbi admite los siguientes tipos como argumentos de


declaración SQL:

• Primitivos: boolean, byte, short, int, long, char, float, y double


• java.lang: Boolean, Byte, Short, Integer, Long, Character, Float,
Double, String, y Enum (almacenado por defecto con el nombre del
valor de enumeración)
• java.math: BigDecimal
• java.net: Inet4Address, Inet6Address, URL y URI
• java.sql: Blob, Clob, Date, Time y Timestamp
• java.time: Instant, LocalDate, LocalDateTime, LocalTime,
OffsetDateTime, ZonedDateTime y ZoneId
• java.util: Date, Optional (cualquier otro tipo de dato soportado), and
UUID
• java.util.Collection y arreglos (arrays) Java (almacenados como SQL
arrays). Es posible que se requiera alguna configuración adicional
según el tipo de elemento del arreglo.

23
3.1.2.2.4. Argumentos Vinculantes (Binding)

Los argumentos de la declaración SQL se pueden vincular de diferentes


maneras:

a) Vincular argumentos individuales:

handle.createUpdate("insert into contactos (id, nombre) values (:id, :name)")


.bind("id", 1)
.bind("nombre", "Alice")
.execute();

b) Vincular múltiples argumentos a la vez desde las entradas a Map:

Map<String, Object> contact = new HashMap<>();


contact.put("id", 2)
contact.put("nombre", "Bob");

handle.createUpdate("insert into contactos (id, nombre) values (:id, :name)")


.bindMap(contact)
.execute();

c) Vincular varios valores a la vez, desde una lista, List<T>, o un vararg,


métodos que necesitan tomar un número variable de argumentos.

List<String> keys = new ArrayList<String>()


keys.add("usuario");
keys.add("direccion");

handle.createQuery("SELECT value FROM items WHERE kind in (<listOfKinds>)")


.bindList("listOfKinds", keys)
.mapTo(String.class)
.list();

// Utilizando 'vararg'
handle.createQuery("SELECT value FROM items WHERE kind in (<varargListOfKinds>)")
.bindList("varargListOfKinds", "usuario", "documentos", "direccion", "departamento")
.mapTo(String.class)
.list();

24
d) Vincular múltiples argumentos de las propiedades de un Java Bean:

Contact contact = new Contact();


contact.setId(3);
contact.setName("Cindy");

handle.createUpdate("insert into contacts (id, name) values (:id, :name)")


.bindBean(contact)
.execute();

e) Vincular campos públicos de objeto:

Object contact = new Object() {


public int id = 0;
public String name = "Cindy";
};

handle.createUpdate("insert into contactos (id, nombre) values (:id, :name)")


.bindFields(contact)
.execute();

f) Vincular métodos públicos y sin parámetro de un Objeto:

Object contact = new Object() {


public int theId() {
return 0;
}

public String theName() {


return "Cindy";
}
};

handle.createUpdate("insert into contactos (id, nombre) values (:theId, :theName)")


.bindMethods(contact)
.execute();

g) Opcionalmente, existe la vinculación por prefijo, que ayuda a eliminar la


ambigüedad en situaciones donde dos o más bean enlazados tienen
nombres de propiedad similares:

25
Folder folder = new Folder(1, "Important Documents");
Document document =
new Document(100, "memo.txt", "Business business business. Numbers.");

handle.createUpdate("insert into documents (id, folder_id, name, contents) " +


"values (:d.id, :f.id, :d.name, :d.contents)")
.bindBean("f", folder)
.bindMethods("f", folder)
.bindFields("d", document)
.execute();

3.1.2.2.5. Argumentos Personalizados

Ocasionalmente, su modelo de datos utilizará tipos de datos que Jdbi no


admite de forma nativa; sin embargo, en Jdbi posee la configuración de
enlazar tipos de datos personalizados como argumentos, mediante la
implementación de algunas interfaces simples:

a) Argumento (Argument)

La interfaz Argument envuelve a un valor único en un enlace

static class UUIDArgument implements Argument {


private UUID uuid;

UUIDArgument(UUID uuid) {
this.uuid = uuid;
}

@Override
public void apply(int position, PreparedStatement statement, StatementContext ctx)
throws SQLException {
statement.setString(position, uuid.toString());
}
}

@Test
public void uuidArgument() {
UUID u = UUID.randomUUID();
assertThat(handle.createQuery("SELECT CAST(:uuid AS VARCHAR)")
.bind("uuid", new UUIDArgument(u))
.mapTo(String.class)
.one()).isEqualTo(u.toString());
}

26
b) ArgumentFactory

La interfaz ArgumentFactory proporciona instancias de Argument para


cualquier tipo de datos que conozca. Al implementar ArgumentFactory es
posible vincular tipos de datos personalizados sin tener que envolverlos
explícitamente en objetos Argument.

Jdbi proporciona una clase llamada: AbstractArgumentFactory que


simplifica la implementación del ArgumentFactory.

static class UUIDArgumentFactory extends AbstractArgumentFactory<UUID> {


UUIDArgumentFactory() {
super(Types.VARCHAR);
}

@Override
protected Argument build(UUID value, ConfigRegistry config) {
return (position, statement, ctx) -> statement.setString(position, value.toString());
}
}

@Test
public void uuidArgumentFactory() {
UUID u = UUID.randomUUID();
handle.registerArgument(new UUIDArgumentFactory());
assertThat(handle.createQuery("SELECT CAST(:uuid AS VARCHAR)")
.bind("uuid", u)
.mapTo(String.class)
.one()).isEqualTo(u.toString());
}

c) Argumentos Preparados

Los ArgumentFactory generalmente se vinculan según el tipo o valor real de


la vinculación, esto es muy flexible; pero cuando se vincula una gran
cantidad, PreparedBatch, el rendimiento (performance) disminuirá ya que se
debe consultar a todos los ArgumentFactory por cada lote de argumentos

27
añadidos. Para solucionar el inconveniente se implementa
ArgumentFactory.Preparable que maneja todos los valores de Type.

d) Registro de Argumentos

Cuando se registra un ArgumentFactory, se almacena en una instancia


Arguments gestionada por Jdbi. Arguments es una clase de configuración
que almacena todos los ArgumentFactory.

Adicionalmente, cuando se vincula argumentos a una declaración, Jdbi


consulta el objeto de configuración: Arguments y busca un ArgumentFactory
apropiado para convertir el objeto vinculado a un Argument.

28
CUADRO DE COMPARACIÓN JDBI VS FRAMEWORKS DE PERSISTENCIA

Características MyBATIS Hibernate JPA JDBI


Simplicidad Muy bueno Bueno Bueno Muy Bueno
Solución completa ORM Mejorable Muy bueno Muy bueno No soportado
Adaptabilidad a
cambios en el modelo Bueno Mejorable Mejorable No soportado
de datos
Complejidad Muy bueno Mejorable Mejorable Muy buena

La dependencia de SQL Bueno Mejorable Mejorable Muy bueno

Rendimiento Bueno Muy bueno - Muy bueno


Portabilidad a través de
diferentes bases de Mejorable Muy bueno - Mejorable
datos relacionales
Portabilidad a las
Muy bueno Bueno No soportado No soportado
plataformas de no-Java

Comunidad de soporte y
Mejorable Muy bueno Muy bueno Mejorable
documentación

Soporta la composición de Framework ORM, que Estándar Java ORM que Jdbi es una librería SQL
sentencias SQL dinámicas sigue el estándar JPA sirve para almacenar, para el lenguaje de
mediante un lenguaje con disponible en Java y en acceder y administrar programación JAVA,
Relevancia del sintaxis tipo XML .Net objetos Java en una base expone el acceso a las
Framework o Librería de datos relacional bases de datos
mediante XML o relacionales en Java de
anotaciones forma idiomática.
3.2. SISTEMA ADMINISTRADOR DE BASE DE DATOS

Es el encargado de:
• Mantener las relaciones entre la información y la Base de Datos.
• Asegurar que la información es almacenada correctamente, es decir,
que las reglas que definen las relaciones entre los datos no sean
violadas.
• Recuperar toda la información en un punto conocido en caso de que el
sistema falle (Gretel, SCRIBD, 2013).

En la actualidad uno de los métodos preferible para el almacenamiento de


datos son los sistemas de administración de base de datos, los más
populares son SQL-Server, Oracle, PostgreSQL, MySQL. La ventaja de
utilizar bases de datos es que lo datos están almacenados en archivos
normalizados reconocidos por varios gestores entre sí.

3.2.1. PostgreSQL

PostgreSQL Server es un sistema de gestión de base de datos (RDBMS


Relational Database Management System) orientado a objetos y de código
abierto, publicado bajo la licencia PostreSQL (Wikipedia contributors, 2020).

Las características más importantes de PostgreSQL son:


• Alta concurrencia
Mediante un sistema denominado MVCC (Acceso concurrente
multiversión, por sus siglas en inglés) PostgreSQL permite que
mientras un proceso escribe en una tabla, otros accedan a la misma

30
tabla sin necesidad de bloqueos. Cada usuario obtiene una visión
consistente.

• Amplia variedad de tipos nativos


PostgreSQL provee nativamente soporte para:

o Números de precisión arbitraria.


o Texto de largo ilimitado.
o Figuras geométricas (con una variedad de funciones
asociadas).
o Direcciones IP (IPv4 e IPv6).
o Bloques de direcciones estilo CIDR.
o Direcciones MAC.
o Arrays.
Adicionalmente los usuarios pueden crear sus propios tipos de datos,
los que pueden ser por completo indexables gracias a la
infraestructura GiST de PostgreSQL. Algunos ejemplos son los tipos
de datos GIS creados por el proyecto PostGIS.

• Integridad transaccional

• Herencia de tablas

• Tipos de datos y operaciones geométricas

• Soporte para transacciones distribuidas


Permite a PostgreSQL integrarse en un sistema distribuido formado
por varios recursos (por ejemplo, una base de datos PostgreSQL, otra
Oracle, una cola de mensajes IBM MQ JMS y un ERP SAP)

31
gestionados por un servidor de aplicaciones donde el éxito ("commit")
de la transacción global es el resultado del éxito de las transacciones
locales.

3.3. SERVICIOS WEB (WEB SERVICES)

Un Servicio Web es un término que describe una colección de protocolos


normalizados de la industria y de servicios utilizados para facilitar el nivel de
interoperabilidad entre aplicaciones. En otras palabras, si una aplicación
puede accederse desde una red que utiliza protocolos como http o XML,
entonces es un Servicio Web. (Tidwell, Snell, & Kulchenko, 2012)

Los servicios web son desarrollados porque en muchos casos las


aplicaciones residen en hardware diferente y corren en sistemas operativos
diferentes, razones por las cuales las aplicaciones deben tener las siguientes
características: (Short, 2002)
• Interoperabilidad El servicio remoto debe poder ser consumido por
clientes de otras plataformas.
• Amigabilidad de Internet La solución debe trabajar bien para clientes
de apoyo que acceden al servicio remoto desde Internet.
• Interfaces fuertemente identificadas no debe existir ambigüedad
entre el tipo de datos enviados y recibidos desde un servicio remoto.
Además, los tipos de datos definidos por el servicio remoto deben
proyectarse razonablemente bien a los tipos de datos definidos por la
mayoría de los lenguajes de programación.
• Habilidad para utilizar las normas existentes de Internet La
implementación del servicio remoto debe utilizar las normas de

32
Internet para evitar la reinvención de soluciones a problemas que ya
fueron resueltos.
• Soporte para cualquier Lenguaje de Programación La solución no
debe acoplarse herméticamente a un lenguaje de programación en
particular. El cliente debe poder implementar un nuevo Servicio Web
(Web Service) o usar uno existente sin tomar en cuenta el lenguaje de
programación en el que fue desarrollado.
• Soporte para cualquier infraestructura de componentes
distribuida La solución no debe acoplarse herméticamente a una
infraestructura de componentes en particular. De hecho, no se debe
exigir que se compre, instale o mantenga una infraestructura de
objetos distribuida sólo por desarrollar un nuevo servicio remoto o
consumir un servicio existente.

3.3.1. Jersey RESTful Web Services

Desarrollar servicios web RESTful que admitan sin problemas la exposición


de sus datos en una variedad de tipos de medios de representación y
abstraiga los detalles de bajo nivel de la comunicación cliente-servidor no es
una tarea fácil sin un buen conjunto de herramientas. Para simplificar el
desarrollo de los servicios web RESTful y sus clientes en Java, se ha
diseñado una API JAX-RS estándar y portátil. La estructura de trabajo
(framework) Jersey RESTful Web Services de código abierto es un
framework en Java que proporciona soporte para las API JAX-RS y sirve
como implementación de referencia JAX-RS (JSR 311 y JSR 339).

Jersey es más que la implementación de referencia JAX-RS. Jersey


proporciona su propia API que amplía las herramientas JAX-RS con
funciones y utilidades adicionales para simplificar aún más el servicio

33
RESTful y el desarrollo del cliente. Jersey también expone numerosas
extensiones de SPI (Service Provider Interface) para que los desarrolladores
puedan utilizar Jersey según sus necesidades.

Los objetivos del proyecto Jersey se pueden resumir en lo siguiente:

La API JAX-RS encamina y proporciona lanzamientos regulares de


implementaciones de referencia de calidad de producción que se acoplan
con GlassFish; también proporciona aplicaciones para extender Jersey y
construir una comunidad de usuarios y desarrolladores. Finalmente facilita la
creación de servicios web RESTful utilizando Java y la máquina virtual Java
(JVM) (Eclipse Foundation, 2020).

34
3.4. ÍTEM CUENTAS POR COBRAR: PLAN DE CUENTAS
CONTABLE

Figura 11 Cuentas por Cobrar

Las cuentas por cobrar son: reclamos exigibles legalmente para el pago
retenido por una empresa por bienes suministrados y/o servicios prestados
que los clientes han ordenado; pero no han pagado. Por lo general, se trata
de facturas generadas por una empresa y entregadas al cliente para su pago
dentro de un plazo acordado. Las cuentas por cobrar se muestran en un
balance general como un activo.

Es una de una serie de transacciones contables relacionadas con la


facturación de un cliente por bienes y servicios que el cliente ha ordenado.
Estos pueden distinguirse de los documentos por cobrar, que son deudas
creadas a través de instrumentos legales formales llamados pagarés.

35
Las cuentas por cobrar representan el dinero que las entidades deben a la
empresa por la venta de productos o servicios a crédito. En la mayoría de las
entidades comerciales, las cuentas por cobrar se ejecutan generalmente
generando una factura y enviándola por correo o por algún otro medio al
cliente, quien, a su vez, debe pagarla dentro de un plazo establecido,
llamado: términos de crédito o términos de pago (Wikipedia contributors,
2020).

A continuación, se muestra la ficha registro que tiena una empresa para


llevar el control de las cuentas por cobrar de sus clientes.

Cliente: Amador Ávila


Fecha Concepto Ingreso Egreso Total
01/01/2020 Por: Arroz 1,000.00 Bs
01/02/2020 Pago de: Arroz 300.00 Bs
01/03/2020 Por: Arroz 500.00 Bs
01/04/2020 Por: Fideo 2,000.00 Bs
01/05/2020 Pago de: Arroz 1,000.00 Bs
01/06/2020 Pago de: Fideo 400.00 Bs

SALDO Ingreso - Egreso 3,500.00 Bs 1,700.00 Bs 1,800.00 Bs

Figura 12 Registro de Cuentas por cobrar

36
CAPÍTULO IV: APLICACIÓN PRÁCTICA
DESARROLLO DEL SERVICIO WEB “DENARIUS”

En esta sección se desarrollará la exposición del Servicio Web “denarius”,


cuentas por cobrar, que sirve para llevar el registro y seguimiento de los
deudores o clientes de una empresa que proporciona diversos artículos.

Para dicho propósito se emplearán o utilizarán todos los conceptos descritos


en el capítulo previo.

4.1. CREACIÓN DE LA BASE DE DATOS

La siguiente figura muestra el Diagrama Entidad Relación que tiene denarius:

Figura 13 Modelo Entidad Relación “denarius”

37
Para llevar el Diagrama Entidad Relación de denarius a: la definición y la
manipulación de datos DDL (Data Definition Language) y DML (Data
Manipulation Languages) se escribió el Siguiente guion (Script) en SQL, el
cual debe ser ejecutado en alguna herramienta que soporte PL/pgSQL
(Procedural Language/PostgreSQL):

CREATE DATABASE "denarius";


\connect denarius;
/*
CREACION DE TABLAS
*/

CREATE TABLE deudores


(
id_deudor serial NOT NULL PRIMARY KEY,
deudor character varying(200) NOT NULL,
telefono character varying(30) NOT NULL,
activo boolean NOT NULL DEFAULT(TRUE),
UNIQUE(deudor)
);
CREATE TABLE articulos
(
id_articulo serial NOT NULL PRIMARY KEY,
articulo character varying(200) NOT NULL,
descripcion character varying(200) NOT NULL,
activo boolean NOT NULL DEFAULT(TRUE),
UNIQUE(articulo)
);
CREATE TABLE movimientos
(
id_movimiento serial NOT NULL PRIMARY KEY,
id_deudor integer NOT NULL,
fecha_movimiento date NOT NULL,
id_articulo integer NOT NULL,
monto_monetario numeric(15,6) NOT NULL,
ingreso boolean NOT NULL,
eliminado boolean DEFAULT(FALSE),
FOREIGN KEY (id_deudor) REFERENCES deudores (id_deudor),
FOREIGN KEY (id_articulo) REFERENCES articulos (id_articulo)
);

CREATE TABLE tipo_usuarios(


id_tipo_usuario serial NOT NULL PRIMARY KEY,
tipo_usuario varchar(35) NOT NULL,
activo boolean NOT NULL DEFAULT(TRUE),
UNIQUE (tipo_usuario)
);
CREATE TABLE usuarios (
id_usuario serial NOT NULL PRIMARY KEY,
usuario character varying(15) NOT NULL,
contrasenia character varying(255) NOT NULL,
id_tipo_usuario integer NOT NULL,

38
activo boolean NOT NULL DEFAULT(TRUE),
UNIQUE(usuario),
FOREIGN KEY (id_tipo_usuario)
REFERENCES tipo_usuarios (id_tipo_usuario)
);
CREATE TABLE bitacora (
id_bitacora serial NOT NULL PRIMARY KEY,
fecha timestamp DEFAULT(now()) NOT NULL,
id_usuario serial NOT NULL,
accion character varying(200) NOT NULL,
FOREIGN KEY (id_usuario)
REFERENCES usuarios(id_usuario)
);
CREATE OR REPLACE VIEW vw_saldos AS
SELECT DISTINCT
movimientos.id_deudor,
totalIngreso,
CASE
WHEN totalEgreso IS NULL THEN '0'
ELSE totalEgreso
END AS totalEgreso,
CASE
WHEN (totalIngreso-totalEgreso) IS NULL
THEN totalIngreso
ELSE(totalIngreso-totalEgreso)
END AS saldo
FROM public.movimientos AS movimientos
JOIN(
SELECT id_deudor,
SUM(monto_monetario) totalIngreso
FROM public.movimientos
WHERE ingreso AND NOT eliminado
GROUP BY id_deudor) AS ingresos
ON movimientos.id_deudor = ingresos.id_deudor
LEFT JOIN(
SELECT id_deudor,
SUM(monto_monetario) AS totalEgreso
FROM public.movimientos
WHERE NOT ingreso AND NOT eliminado
GROUP BY id_deudor) AS egresos
ON movimientos.id_deudor = egresos.id_deudor
ORDER BY id_deudor
;
/*
INSERCIÓN DE REGISTROS
*/

INSERT INTO public.tipo_usuarios(tipo_usuario, activo)


VALUES ('administrador', TRUE),
('operador', TRUE)
;
INSERT INTO public.usuarios(usuario, contrasenia, id_tipo_usuario, activo)
VALUES ('jrodriguez', '123456', 1, TRUE),
('vcabrera', '234567', 1, TRUE),
('nmendoza', '345678', 2, TRUE),
('amartinez', '456789', 2, TRUE)
;
INSERT INTO public.articulos(articulo, descripcion, activo)
VALUES ('ARROZ', 'SEMILLA COMESTIBLE', TRUE),
('FIDEO', 'PASTA HECHA A BASE DE HUEVO Y HARINA', TRUE),

39
('CAFE', 'GRANO TOSTADO ELABORADO A PARTIR DEL FRUTO DE LA PLANTA DEL CAFE',
TRUE),
('CHOCOLATE', 'ALIMENTO ELABORADO A PARTIR DE LA SEMILLA DEL ARBOL DE CACAO',
TRUE),
('TE','HOJAS OBTENIDAS DEL PLANTA DEL TE, UTILIZADAS PARA REALIZAR INFUSIONES ',
TRUE);
INSERT INTO public.deudores(deudor, telefono, activo)
VALUES ('AMADOR AVILA', '78945612', TRUE),
('BORIS BUSTILLOS', '71234567', TRUE),
('CARLOS CESPEDES', '72345678', TRUE);
INSERT INTO public.movimientos(id_deudor, fecha_movimiento, id_articulo, monto_monetario,
ingreso, eliminado)
-- Deudor 1 (Amador Avila)
VALUES (1, '2020-01-01', 1, 1000, TRUE, FALSE),
(1, '2020-02-01', 1, 300, FALSE, FALSE),
(1, '2020-03-01', 1, 500, TRUE, FALSE),
(1, '2020-04-01', 2, 2000, TRUE, FALSE),
(1, '2020-05-01', 1, 1000, FALSE, FALSE),
(1, '2020-06-01', 2, 400, FALSE, FALSE),

-- Deudor 2 (Boris Burgos)


(2, '2020-01-01', 3, 500, TRUE, FALSE),
(2, '2020-02-01', 3, 100, FALSE, FALSE),
(2, '2020-03-01', 3, 500, TRUE, FALSE),
(2, '2020-04-01', 3, 300, TRUE, FALSE),
(2, '2020-05-01', 3, 1000, FALSE, FALSE),
(2, '2020-06-01', 3, 200, FALSE, FALSE),

-- Deudor 3 (Carlos Cespedes)


(3, '2020-01-01', 4, 1500, TRUE, FALSE),
(3, '2020-02-01', 4, 1000, FALSE, FALSE),
(3, '2020-03-01', 5, 600, TRUE, FALSE),
(3, '2020-04-01', 3, 700, TRUE, FALSE),
(3, '2020-04-15', 3, 500, FALSE, FALSE),
(3, '2020-05-01', 3, 100, FALSE, FALSE),
(3, '2020-05-15', 5, 600, FALSE, FALSE),
(3, '2020-06-01', 4, 500, FALSE, FALSE),
(3, '2020-06-15', 3, 100, FALSE, FALSE)
;

40
4.2. DESARROLLO DEL SERVICIO WEB

Crear un proyecto Web Maven en el IDE de preferencia, para el ejemplo


utilizaremos Apache NetBeans:

Figura 14 Proyecto Web con Maven en Apache Netbeans 11

Elegir Apache Tomcat como servidor de Aplicaciones Web:

Figura 15 Elección de Servidor Web y Versión de Java a utilizar

41
Una vez presionado el botón “Finish” el proyecto tendrá la siguiente
estructura:

Figura 16 Estructura del Proyecto Maven: “DenariusRestJdbi”

4.2.1. Archivo pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/mave
n-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.vca</groupId>
<artifactId>DenariusRestJdbi</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>DenariusRestJdbi</name>
<properties>
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<!-- REST Jersey -->
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>

42
<artifactId>jersey-container-servlet</artifactId>
<version>2.21.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.21.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.21.1</version>
</dependency>
<!-- PostgreSQL -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.4.1212</version>
</dependency>
<!-- JDBI -->
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-core</artifactId>
<type>jar</type>
<version>3.14.1</version>
</dependency>
<!-- Para mapeo -->
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-sqlobject</artifactId>
<version>3.14.1</version>
</dependency>
<!-- Fin mapeo -->
<dependency>
<groupId>org.jdbi</groupId>
<artifactId>jdbi3-postgres</artifactId>
<type>pom</type>
<version>3.14.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArguments>
<endorseddirs>${endorsed.dir}</endorseddirs>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>

43
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${endorsed.dir}</outputDirectory>
<silent>true</silent>
<artifactItems>
<artifactItem>
<groupId>javax</groupId>
<artifactId>javaee-endorsed-api</artifactId>
<version>7.0</version>
<type>jar</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

4.2.2. Archivo web.xml

Figura 17 Localización del Archivo: “web.xml”, proyecto Maven

44
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">

<display-name>Restful Web Application</display-name>

<servlet>
<servlet-name>ServicioDenarius</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.vca.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServicioDenarius</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>

</web-app>

Crear los siguientes. Paquetes:

Figura 18 Localización de Paquetes

45
4.2.3. Db.properties

Dentro de la carpeta src/main/resources crear el archivo db.properties,


cambiando los datos de Usuario y Contraseñas en caso de ser diferentes a la
figura que se detalla a continuación:

Figura 19 Archivo: “db.properties”

Dentro del paquete com.vca.fuenteDatos crear la clase dbProperties.java

Figura 20 Localización: Clase “dbProperties.java”

46
package com.vca.fuenteDatos;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class dbProperties {


public String getValorPropiedad(String nombrePropiedad){
String valorPropiedad = "";
Properties propiedad = new Properties();
try{
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("db.properties");
propiedad.load(inputStream);
valorPropiedad = propiedad.getProperty(nombrePropiedad);
}catch (IOException e){
System.out.println(e);
}
return valorPropiedad;
}
}

4.2.4. ConectorBD

A continuación, crear la clase conectorBD.java

Figura 21 Localización: Clase “conectorBD.java”

package com.vca.fuenteDatos;
import org.jdbi.v3.core.Jdbi;
import org.postgresql.ds.PGSimpleDataSource;
public class conectorBD {
public Jdbi getJdbi(){
dbProperties propiedades = new dbProperties();

47
PGSimpleDataSource ds = new PGSimpleDataSource();
ds.setUrl(propiedades.getValorPropiedad("BD_Url"));
ds.setUser(propiedades.getValorPropiedad("BD_USUARIO"));
ds.setPassword(propiedades.getValorPropiedad("BD_CONTRASENIA"));
ds.setLoadBalanceHosts(true);
Jdbi jdbi = Jdbi.create(ds);

return jdbi;
}
}

4.2.5. Data Transfer Objects

Dentro del paquete com.vca.dto crear los archivos: Articulos.java,


Deudores.java, Movimientos.java, Saldos.java, Tipo_usuarios.java y Usuarios

Figura 22 Localización: Clases DTO

4.2.5.1. Articulos.java

package com.vca.dto;

public class Articulos {


private Integer id_articulo;
private String articulo;
private String descripcion;
private Boolean activo;

48
public Articulos(Integer id_articulo, String articulo, String descripcion, Boolean activo) {
this.id_articulo = id_articulo;
this.articulo = articulo;
this.descripcion = descripcion;
this.activo = activo;
}

public Articulos(String articulo, String descripcion, Boolean activo) {


this.articulo = articulo;
this.descripcion = descripcion;
this.activo = activo;
}

public Articulos() {
}

public Integer getId_articulo() {


return id_articulo;
}

public void setId_articulo(Integer id_articulo) {


this.id_articulo = id_articulo;
}

public String getArticulo() {


return articulo;
}

public void setArticulo(String articulo) {


this.articulo = articulo;
}

public String getDescripcion() {


return descripcion;
}

public void setDescripcion(String descripcion) {


this.descripcion = descripcion;
}

public Boolean getActivo() {


return activo;
}

public void setActivo(Boolean activo) {


this.activo = activo;
}

49
4.2.5.2. Deudores.java
package com.vca.dto;

public class Deudores {


private Integer id_deudor;
private String deudor;
private String telefono;
private Boolean activo;

public Deudores(Integer id_deudor, String deudor, String telefono, Boolean activo) {


this.id_deudor = id_deudor;
this.deudor = deudor;
this.telefono = telefono;
this.activo = activo;
}

public Deudores(String deudor, String telefono, Boolean activo) {


this.deudor = deudor;
this.telefono = telefono;
this.activo = activo;
}

public Deudores(){

public Integer getId_deudor() {


return id_deudor;
}

public String getDeudor() {


return deudor;
}

public String getTelefono() {


return telefono;
}

public Boolean getActivo() {


return activo;
}

public void setId_deudor(Integer id_deudor) {


this.id_deudor = id_deudor;
}

public void setDeudor(String deudor) {


this.deudor = deudor;
}

public void setTelefono(String telefono) {


this.telefono = telefono;
}

public void setActivo(Boolean activo) {


this.activo = activo;
}
}

50
4.2.5.3. Movimientos.java

package com.vca.dto;

import java.math.BigDecimal;
import java.time.LocalDate;

public class Movimientos {


private Integer id_movimiento ;
private Integer id_deudor;
private LocalDate fecha_movimiento;
private Integer id_articulo;
private BigDecimal monto_monetario;
private Boolean ingreso;
private Boolean eliminado;

public Movimientos(Integer id_movimiento, Integer id_deudor, LocalDate fecha_movimiento, Integer


id_articulo, BigDecimal monto_monetario, Boolean ingreso, Boolean eliminado) {
this.id_movimiento = id_movimiento;
this.id_deudor = id_deudor;
this.fecha_movimiento = fecha_movimiento;
this.id_articulo = id_articulo;
this.monto_monetario = monto_monetario;
this.ingreso = ingreso;
this.eliminado = eliminado;
}

public Movimientos(Integer id_deudor, LocalDate fecha_movimiento, Integer id_articulo, BigDecimal


monto_monetario, Boolean ingreso, Boolean eliminado) {
this.id_deudor = id_deudor;
this.fecha_movimiento = fecha_movimiento;
this.id_articulo = id_articulo;
this.monto_monetario = monto_monetario;
this.ingreso = ingreso;
this.eliminado = eliminado;
}

public Movimientos() {
}

public Integer getId_movimiento() {


return id_movimiento;
}

public void setId_movimiento(Integer id_movimiento) {


this.id_movimiento = id_movimiento;
}

public Integer getId_deudor() {


return id_deudor;
}

public void setId_deudor(Integer id_deudor) {


this.id_deudor = id_deudor;
}

public LocalDate getFecha_movimiento() {

51
return fecha_movimiento;
}

public void setFecha_movimiento(LocalDate fecha_movimiento) {


this.fecha_movimiento = fecha_movimiento;
}

public Integer getId_articulo() {


return id_articulo;
}

public void setId_articulo(Integer id_articulo) {


this.id_articulo = id_articulo;
}

public BigDecimal getMonto_monetario() {


return monto_monetario;
}

public void setMonto_monetario(BigDecimal monto_monetario) {


this.monto_monetario = monto_monetario;
}

public Boolean getIngreso() {


return ingreso;
}

public void setIngreso(Boolean ingreso) {


this.ingreso = ingreso;
}

public Boolean getEliminado() {


return eliminado;
}

public void setEliminado(Boolean eliminado) {


this.eliminado = eliminado;
}

52
4.2.5.4. Saldos.java
package com.vca.dto;

import java.math.BigDecimal;

public class Saldos {


private Integer id_deudor;
private BigDecimal totalIngreso;
private BigDecimal totalEgreso;
private BigDecimal saldo;

public Integer getId_deudor() {


return id_deudor;
}

public BigDecimal getSaldo() {


return saldo;
}

public void setId_deudor(Integer id_deudor) {


this.id_deudor = id_deudor;
}

public void setSaldo(BigDecimal saldo) {


this.saldo = saldo;
}

public BigDecimal getTotalIngreso() {


return totalIngreso;
}

public void setTotalIngreso(BigDecimal totalIngreso) {


this.totalIngreso = totalIngreso;
}

public BigDecimal getTotalEgreso() {


return totalEgreso;
}

public void setTotalEgreso(BigDecimal totalEgreso) {


this.totalEgreso = totalEgreso;
}

public Saldos() {

public Saldos(Integer id_deudor, BigDecimal totalIngreso, BigDecimal totalEgreso, BigDecimal saldo)


{
this.id_deudor = id_deudor;
this.totalIngreso = totalIngreso;
this.totalEgreso = totalEgreso;
this.saldo = saldo;
}

53
4.2.5.5. Tipo_usuarios.java

package com.vca.dto;

public class Tipo_usuarios {


private Integer id_tipo_usuario;
private String tipo_usuario;
private Boolean activo;

public Tipo_usuarios(Integer id_tipo_usuario, String tipo_usuario, Boolean activo) {


this.id_tipo_usuario = id_tipo_usuario;
this.tipo_usuario = tipo_usuario;
this.activo = activo;
}

public Tipo_usuarios(String tipo_usuario, Boolean activo) {


this.tipo_usuario = tipo_usuario;
this.activo = activo;
}

public Tipo_usuarios() {
}

public int getId_tipo_usuarios() {


return id_tipo_usuario;
}

public void setId_tipo_usuario(int id_tipo_usuario) {


this.id_tipo_usuario = id_tipo_usuario;
}

public String getTipo_usuario() {


return tipo_usuario;
}

public void setTipo_usuario(String tipo_usuario) {


this.tipo_usuario = tipo_usuario;
}

public Boolean getActivo() {


return activo;
}

public void setActivo(Boolean activo) {


this.activo = activo;
}

54
4.2.5.6. Usuarios.java

package com.vca.dto;

public class Usuarios {


private int id_usuario;
private String usuario;
private String contrasenia;
private Integer id_tipo_usuario;
private Boolean activo;

public Usuarios(int id_usuario, String usuario, String contrasenia,Integer id_tipo_usuario ,Boolean


activo) {
this.id_usuario = id_usuario;
this.usuario = usuario;
this.contrasenia = contrasenia;
this.id_tipo_usuario = id_tipo_usuario;
this.activo = activo;
}
public Usuarios(String usuario, String contrasenia, Integer id_tipo_usuario,Boolean activo) {
this.usuario = usuario;
this.contrasenia = contrasenia;
this.id_tipo_usuario = id_tipo_usuario;
this.activo = activo;
}

public Usuarios(){

public int getId_usuario() {


return id_usuario;
}

public String getUsuario() {return usuario; }

public String getContrasenia() { return contrasenia;}

public Integer getId_tipo_usuario() {


return id_tipo_usuario;
}
public Boolean getActivo() {return activo;}
public void setId_usuario(int id_usuario) {
this.id_usuario = id_usuario;
}

public void setUsuario(String usuario) {this.usuario = usuario;}

public void setContrasenia(String contrasenia) {this.contrasenia = contrasenia;}

public void setId_tipo_usuario(Integer id_tipo_usuario) {


this.id_tipo_usuario = id_tipo_usuario;
}

public void setActivo(Boolean activo) {this.activo = activo; }

55
4.2.6. Data Access Objects

Para utilizar el estilo del API declarativa se crearon cuatro interfaces de


acceso de datos (DAO) que deben ser creados dentro del paquete:
com.vca.dao

Figura 23 Localización de: Interfaces DAO

4.2.6.1. ArticulosDAO.java

package com.vca.dao;

/**
*
* @author Vladimir Cabrera Arandia
* @version 1.2
*/
import com.vca.dto.Articulos;
import java.util.List;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

public interface ArticulosDAO {

@SqlUpdate("CREATE TABLE articulos (\n"


+ "id_articulo serial NOT NULL PRIMARY KEY,\n"
+ "articulo character varying(200) NOT NULL,\n"
+ "descripcion character varying(200) NOT NULL,\n"
+ "activo boolean NOT NULL DEFAULT(TRUE),\n"
+ "UNIQUE(articulo))")
void crearTabla();

56
@SqlUpdate("INSERT INTO articulos(articulo, descripcion) VALUES (?, ?)")
void insertarArticulo(String articulo, String descripcion);

@SqlUpdate("UPDATE articulos SET articulo=?, descripcion=?, activo=? WHERE id_articulo=?")


void actualizarArticulo(String articulo, String descripcion, Boolean activo, Integer id_articulo);

@SqlQuery("SELECT * FROM articulos WHERE activo=true ORDER BY articulos")


@RegisterBeanMapper(Articulos.class)
List<Articulos> articulos();

@SqlQuery("SELECT * FROM articulos WHERE activo=false ORDER BY articulos")


@RegisterBeanMapper(Articulos.class)
List<Articulos> articulosEliminados();

4.2.6.2. MovimentosDAO.java

package com.vca.dao;

import com.vca.dto.Articulos;
import java.util.List;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

public interface ArticulosDAO {

@SqlUpdate("CREATE TABLE articulos (\n"


+ "id_articulo serial NOT NULL PRIMARY KEY,\n"
+ "articulo character varying(200) NOT NULL,\n"
+ "descripcion character varying(200) NOT NULL,\n"
+ "activo boolean NOT NULL DEFAULT(TRUE),\n"
+ "UNIQUE(articulo))")
void crearTabla();

@SqlUpdate("INSERT INTO articulos(articulo, descripcion) VALUES (?, ?)")


void insertarArticulo(String articulo, String descripcion);

@SqlUpdate("UPDATE articulos SET articulo=?, descripcion=?, activo=? WHERE id_articulo=?")


void actualizarArticulo(String articulo, String descripcion, Boolean activo, Integer id_articulo);

@SqlQuery("SELECT * FROM articulos WHERE activo=true ORDER BY articulos")


@RegisterBeanMapper(Articulos.class)
List<Articulos> articulos();

@SqlQuery("SELECT * FROM articulos WHERE activo=false ORDER BY articulos")


@RegisterBeanMapper(Articulos.class)
List<Articulos> articulosEliminados();

57
4.2.6.3. SaldoDAO.java

package com.vca.dao;

import com.vca.dto.Saldos;
import java.util.List;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

/**
*
* @author Vladimir Cabrera Arandia
* @version 1.3
*/
public interface SaldosDAO {
@SqlUpdate("CREATE OR REPLACE VIEW vw_saldos AS\n"+
"SELECT DISTINCT\n"+
" movimientos.id_deudor,\n"+
" totalIngreso,\n"+
" CASE\n"+
" WHEN totalEgreso IS NULL THEN '0'\n"+
" ELSE totalEgreso\n"+
" END AS totalEgreso,\n"+
" CASE\n"+
" WHEN (totalIngreso-totalEgreso) IS NULL THEN totalIngreso\n"+
" ELSE(totalIngreso-totalEgreso)\n"+
" END AS saldo\n"+
"FROM public.movimientos AS movimientos\n"+
"JOIN(\n"+
" SELECT id_deudor,\n"+
" SUM(monto_monetario) totalIngreso\n"+
" FROM public.movimientos\n"+
" WHERE ingreso AND NOT eliminado\n"+
" GROUP BY id_deudor) AS ingresos\n"+
"ON movimientos.id_deudor = ingresos.id_deudor\n"+
"LEFT JOIN(\n"+
" SELECT id_deudor,\n"+
" SUM(monto_monetario) AS totalEgreso\n"+
" FROM public.movimientos\n"+
" WHERE NOT ingreso AND NOT eliminado\n"+
" GROUP BY id_deudor) AS egresos\n"+
"ON movimientos.id_deudor = egresos.id_deudor\n"+
"ORDER BY id_deudor;")
void crearVista();

@SqlQuery("SELECT id_deudor, totalingreso, totalegreso, saldo FROM vw_saldos ORDER BY


id_deudor;")
@RegisterBeanMapper(Saldos.class)
List<Saldos> saldos();
}

58
4.2.6.4. Tipo_usuariosDAO.java

package com.vca.dao;

import com.vca.dto.Tipo_usuarios;
import java.util.List;
import org.jdbi.v3.sqlobject.config.RegisterBeanMapper;
import org.jdbi.v3.sqlobject.statement.SqlQuery;
import org.jdbi.v3.sqlobject.statement.SqlUpdate;

public interface Tipo_usuariosDAO {

@SqlUpdate("CREATE TABLE tipo_usuarios (\n"


+ "id_tipo_usuario serial NOT NULL PRIMARY KEY,\n"
+ "tipo_usuario varchar(35) NOT NULL,\n"
+ "activo boolean NOT NULL DEFAULT(TRUE),\n"
+ "UNIQUE(tipo_usuario))")
void createTable();

@SqlUpdate("INSERT INTO tipo_usuarios(tipo_usuario) VALUES (?)")


void insertPositional(String tipo_usuario);

@SqlQuery("SELECT * FROM tipo_usuarios ORDER BY tipo_usuarios")


@RegisterBeanMapper(Tipo_usuarios.class)
List<Tipo_usuarios> tipo_usuarios();
}

59
4.2.7. Servicios Rest

Seguidamente debe crear los servicios Rest, empezaremos por los que
acceden a través del estilo de API declarativa, haciendo uso de las interfaces
DAO creadas previamente

4.2.7.1. ServicioArtículos.java

Figura 24 Localización del Servicio REST: “ServicioArticulos.java”

package com.vca.rest;

import com.vca.dao.ArticulosDAO;
import com.vca.dto.Articulos;
import com.vca.fuenteDatos.conectorBD;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.POST;
import javax.ws.rs.Produces;
import javax.ws.rs.PUT;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;

60
@Path("/servicio/articulos")
public class ServicioArticulos {
/**
* Crear a nueva instancia de ServicioArticulos
*/
public ServicioArticulos() {
}
/**
* Recupera la representación de una instancia de com.vca.ServicioArticulos
* @return un mensaje de texto
*/
@GET
@Path("/mensaje")
@Produces(MediaType.TEXT_PLAIN)
public String getText() {
return "Hola ARTICULOS";
}
/**
* Registra un nuevo artículo
* @param particulo Nombre del artículo
* @param pdescripcion Descripción del artículo *
* @return Texto de confirmación de la adición del registro
*/
@POST
@Path("/registro/{particulo}/{pdescripcion}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String registrarArticulo(
@PathParam("particulo") String particulo,
@PathParam("pdescripcion") String pdescripcion) {

Jdbi jdbi = new conectorBD().getJdbi();


jdbi.installPlugin(new SqlObjectPlugin());
try{
jdbi.withExtension(ArticulosDAO.class, dao -> {
dao.insertarArticulo(particulo, pdescripcion);
return dao.articulos();
});
return "ARTICULO insertado correctamente";
}
catch(Exception e){
return e.toString();
}
}
/**
* Modifica un registro de la tabla artículos
* @param particulo
* @param pdescripcion
* @param pactivo
* @param pidarticulo
* @return Texto de confirmación de la modificación del registro
*/
@PUT
@Path("/modificacion/{particulo}/{pdescripcion}/{pactivo}/{pidarticulo}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String modificarArticulo(
@PathParam("particulo") String particulo,
@PathParam("pdescripcion") String pdescripcion,

61
@PathParam("pactivo") Boolean pactivo,
@PathParam("pidarticulo") Integer pidarticulo){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());
try {
jdbi.withExtension(ArticulosDAO.class, dao -> {
dao.actualizarArticulo(particulo, pdescripcion, pactivo, pidarticulo);
return dao.articulos();
});
return "ARTICULO modificado correctamente";
}
catch(Exception e){
return e.toString();
}

}
/**
* Visualiza la lista de artículos
* @return Lista de Articulos
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Articulos> getArticulos(){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Articulos> articulos = jdbi.withExtension(ArticulosDAO.class, dao -> {


return dao.articulos();
});
return articulos;
}

/**
* Visualiza la lista de artículos eliminados
* @return Lista de Articulos
*/
@GET
@Path("/visualizacion/eliminados")
@Produces({MediaType.APPLICATION_JSON})
public List<Articulos> getArticulosEliminados(){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Articulos> articulos = jdbi.withExtension(ArticulosDAO.class, dao -> {


return dao.articulosEliminados();
});
return articulos;
}

62
4.2.7.2. Servicio Movimientos.java

Figura 25 Localización del Servicio REST: “ServicioMovimientos.java”

package com.vca.rest;

import com.vca.dao.MovimientosDAO;
import com.vca.dto.Movimientos;
import com.vca.fuenteDatos.conectorBD;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;

@Path("/servicio/movimientos")
public class ServicioMovimientos {
/**
* Crear una nueva instancia de movimientos
*/
public ServicioMovimientos(){

63
/**
* @since 1.0
* Repuera la representación de uan instacia de com.vca.ServicioMovimientos
* @return mensaje de prueba
*/
@GET
@Path("/mensaje")
@Produces({MediaType.TEXT_PLAIN})
public String getText(){
return "Hola Movimientos";
}

/**
* Registrar un nuevo movimiento
* @param pid_deudor
* @param pfecha_movimiento
* @param pid_articulo
* @param pmonto_monetario
* @param pingreso
* @param peliminado
* @return Texto de confirmación de la adición del registro
*/
@POST
@Path("/registro/{pid_deudor}/{pfecha_movimiento}/{pid_articulo}/{pmonto_monetario}/{pingreso}")
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.TEXT_PLAIN})
public String registrarMovimiento(
@PathParam("pid_deudor") Integer pid_deudor,
@PathParam("pfecha_movimiento") String pfecha_movimiento,
@PathParam("pid_articulo") Integer pid_articulo,
@PathParam("pmonto_monetario")BigDecimal pmonto_monetario,
@PathParam("pingreso")String pingreso
){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

LocalDate fechaLocal = LocalDate.parse(pfecha_movimiento, DateTimeFormatter.ofPattern("d-


MM-yyyy"));
try{
jdbi.withExtension(MovimientosDAO.class, dao ->{
dao.insertarMovimiento(pid_deudor, fechaLocal, pid_articulo, pmonto_monetario, pingre
so.contentEquals("ingreso"));
return dao.movimientos();
});
return "Movimiento insertado correctamente";
}catch (Exception e){
return e.toString();
}
}

/**
* Modifica un registro de la tabla movimientos
* @param pid_movimiento
* @return Texto de confirmación de la adición del registro
*/
@PUT
@Path("/modificacion/{pid_movimiento}")
@Consumes(MediaType.APPLICATION_JSON)

64
@Produces({MediaType.TEXT_PLAIN})
public String modificarMovimiento(@PathParam("pid_movimiento") Integer pid_movimiento){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

try{
jdbi.withExtension(MovimientosDAO.class, dao ->{
dao.actualizarMovimiento(pid_movimiento);
return dao.movimientos();
});
return "Movimiento Modificado correctamente";
}catch(Exception e){
return e.toString();
}
}

/**
* Visualiza la lista de movimientos de un deudor
* @param pid_deudor
* @return Lista de Movimientos de un deudor
*/
@GET
@Path("/visualizacion/{pid_deudor}")
@Produces({MediaType.APPLICATION_JSON})
public List<Movimientos> getMovimientosDeudor(@PathParam("pid_deudor") Integer pid_deudor){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Movimientos> movimientos = jdbi.withExtension(MovimientosDAO.class, dao ->{


return dao.movimientosDeudor(pid_deudor);
});
return movimientos;
}

/**
* Visualiza la lista de movimientos de un deudor
* @return Lista de Movimientos de un deudor
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Movimientos> getMovimientos(){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Movimientos> movimientos = jdbi.withExtension(MovimientosDAO.class, dao ->{


return dao.movimientos();
});
return movimientos;
}

65
4.2.7.3. Servicio Saldos.java

Figura 26 Localización del Servicio REST: “ServicioSaldos.java”

package com.vca.rest;

import com.vca.dao.SaldosDAO;
import com.vca.dto.Saldos;
import com.vca.fuenteDatos.conectorBD;
import java.util.List;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;

/**
*
* @author vladimir.cabrera
* @version 1.3
*
*/
@Path("/servicio/saldos")
public class ServicioSaldos {
/**
* Crear una nueva instancia de deudores
*/
public ServicioSaldos() {

66
/**
* @since 1.0
* Recupera la representación de una isntancia de com.vca.ServicioSaldos
* @return un mensaje de prueba
*/
@GET
@Path("/mensaje")
@Produces({MediaType.TEXT_PLAIN})
public String getText(){
return "Hola Saldos";
}

/**
* Visualiza la lista de Saldos
* @return Lista de Saldos
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Saldos> getSaldos(){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Saldos> saldos = jdbi.withExtension(SaldosDAO.class, dao -> {


return dao.saldos();
});
return saldos;
}

4.2.7.4. Servicio Tipo Usuario.java

Figura 27 Localización del Servicio REST: “ServicioTipo_usuario.java”

67
package com.vca.rest;

import com.vca.dao.Tipo_usuariosDAO;
import com.vca.dto.Tipo_usuarios;
import com.vca.fuenteDatos.conectorBD;
import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.POST;
import javax.ws.rs.PathParam;
import org.jdbi.v3.core.Jdbi;
import org.jdbi.v3.sqlobject.SqlObjectPlugin;

@Path("/servicio/tipo_usuario")
public class ServicioTipo_usuario {
/**
* Crear a nueva instancia de ServicioTipo_usuarios
*/
public ServicioTipo_usuario() {
}

/**
* Recupera la representación de una instancia de com.vca.ServicioArticulos
* @return una instancia de java.lang.String
*/
@GET
@Path("/mensaje")
@Produces(MediaType.TEXT_PLAIN)
public String getText() {
return "Bienvenido a Tipo Usuario";
}

/**
*
* @param ptipo_usuario Nombre del tipo usuario
* @return Texto de confirmación de la adición del registro
*
*/
@POST
@Path("/registro/{ptipo_usuario}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String registrarTipoUsuario(@PathParam("ptipo_usuario") String ptipo_usuario){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());
try{
jdbi.withExtension(Tipo_usuariosDAO.class, dao -> {
dao.insertPositional(ptipo_usuario);
return dao.tipo_usuarios();
});
return "TIPO USUARIO insertado correctamente";
}
catch(Exception e){
return e.toString();
}

68
}

/**
* Recupera la lista total de tipos de usuarios
* @return Lista de tipos de usuarios
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Tipo_usuarios> getTipo_usuarios(){
Jdbi jdbi = new conectorBD().getJdbi();
jdbi.installPlugin(new SqlObjectPlugin());

List<Tipo_usuarios> tipo_usuarios = jdbi.withExtension(Tipo_usuariosDAO.class, dao -> {


return dao.tipo_usuarios();
});
return tipo_usuarios;
}
}

Finalmente crearemos los servicios con estilo API Fluida

4.2.7.5. Servicio Deudores.java

Figura 28 Localización del Servicio REST: “ServicioDeudores.java”

69
package com.vca.rest;

import com.vca.dto.Deudores;
import com.vca.fuenteDatos.conectorBD;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
import org.jdbi.v3.core.Jdbi;

@Path("/servicio/deudores")
public class ServicioDeudores {

/**
* Crear a nueva instancia de ServicioDeudores
*/
public ServicioDeudores() {
}

/**
* @since 1.0
* Recupera la representación de una instancia de com.vca.ServicioDeudores
* @return un mensaje de texto
*
*/
@GET
@Path("/mensaje")
@Produces(MediaType.TEXT_PLAIN)
public String getText() {
return "Hola Deudores";
}

/**
* Registra un nuevo deudor
* @param pdeudor Nombre del deudor
* @param ptelefono Teléfono del deudor
* @return Texto de confirmación de la adición del registro
*/
@POST
@Path("/registro/{pdeudor}/{ptelefono}")
@Consumes(MediaType.APPLICATION_JSON)
public String registrarDeudor(
@PathParam("pdeudor") String pdeudor,
@PathParam("ptelefono") String ptelefono) {

Jdbi jdbi = new conectorBD().getJdbi();


try{
jdbi.useHandle(handle -> {
handle.execute("INSERT INTO deudores (deudor, telefono) values (?, ?)", pdeudor, ptelefo
no);
});
return "DEUDOR insertado correctamente";
}
catch(Exception e){
return e.toString();

70
}
}

/**
* Modifica un resgistro deudor
* @param pdeudor
* @param ptelefono
* @param pactivo
* @param pid_deudor
* @return Texto de confirmación de la modificación del registro
*/
@PUT
@Path("/modificacion/{pdeudor}/{ptelefono}/{pactivo}/{pid_deudor}")
@Consumes(MediaType.APPLICATION_JSON)
public String modificarDeudor(
@PathParam("pdeudor") String pdeudor,
@PathParam("ptelefono") String ptelefono,
@PathParam("pactivo") Boolean pactivo,
@PathParam("pid_deudor") Integer pid_deudor) {

Jdbi jdbi = new conectorBD().getJdbi();


try{
jdbi.useHandle(handle -> {
handle.execute("UPDATE deudores SET deudor =?, telefono=?, activo=? WHERE id_deu
dor=? ", pdeudor, ptelefono, pactivo, pid_deudor);
});
return "DEUDOR modificado correctamente";
}
catch(Exception e){
return e.toString();
}
}

/**
* Visualiza la lista de deudores
* @return Lista de Deudores
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Deudores> getDeudores(){
Jdbi jdbi = new conectorBD().getJdbi();

List<Deudores> deudores = jdbi.withHandle(handle -> {


return handle.createQuery("SELECT * FROM deudores WHERE activo=true ORDER BY deudo
r")
.mapToBean(Deudores.class)
.list();
});

return deudores;
}

/**
* Visualiza la lista de deudores dados de baja
* @return Lista de Deudores
*/
@GET
@Path("/visualizacion/eliminados")
@Produces({MediaType.APPLICATION_JSON})

71
public List<Deudores> getDeudoresEliminados(){
Jdbi jdbi = new conectorBD().getJdbi();

List<Deudores> deudores = jdbi.withHandle(handle -> {


return handle.createQuery("SELECT * FROM deudores WHERE activo=false ORDER BY deud
or")
.mapToBean(Deudores.class)
.list();
});

return deudores;
}
}

4.2.7.6. Servicio Usuarios.java

Figura 29: Localización del Servicio REST: “ServicioUsuarios.java”

package com.vca.rest;

import com.vca.dto.Usuarios;
import com.vca.fuenteDatos.conectorBD;
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.POST;

72
import javax.ws.rs.PUT;
import javax.ws.rs.core.MediaType;
import org.jdbi.v3.core.Jdbi;

@Path("/servicio/usuarios")
public class ServicioUsuarios {

/**
* Crear a nueva instancia de ServicioUsuarios
*/
public ServicioUsuarios() {
}
/**
*
* @param pusuario Nombre del usuario
* @param pcontrasenia Contraseña del usuario
* @param pid_tipo_usuario Tipo de usuario
* @return Texto de confirmación de la adición del registro
*
*/
@POST
@Path("/registro/{pusuario}/{pcontrasenia}/{pid_tipo_usuario}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String registrarUsuario(
@PathParam("pusuario") String pusuario,
@PathParam("pcontrasenia") String pcontrasenia,
@PathParam("pid_tipo_usuario") Integer pid_tipo_usuario) {

Jdbi jdbi = new conectorBD().getJdbi();


try{
jdbi.useHandle(handle -> {
handle.execute("INSERT INTO usuarios (usuario, contrasenia, id_tipo_usuario) values (?, ?,
?)", pusuario, pcontrasenia, pid_tipo_usuario);
});
return "USUARIO insertado correctamente";
}
catch(Exception e){
return e.toString();
}
}

/**
*
* @param pusuario Nombre del usuario
* @param pcontrasenia Contraseña del usuario
* @param pid_tipo_usuario Tipo de usuario
* @param pactivo Saber si está activo
* @param pid_usuario Identificador de usuario
* @return Texto de confirmación de la modificación del registro
*
*/
@PUT
@Path("/modificacion/{pusuario}/{pcontrasenia}/{pid_tipo_usuario}/{pactivo}/{pid_usuario}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_PLAIN)
public String modificaUsuario(
@PathParam("pusuario") String pusuario,
@PathParam("pcontrasenia") String pcontrasenia,
@PathParam("pid_tipo_usuario") Integer pid_tipo_usuario,

73
@PathParam("pactivo") Boolean pactivo,
@PathParam("pid_usuario") Integer pid_usuario) {

Jdbi jdbi = new conectorBD().getJdbi();


try{
jdbi.useHandle(handle -> {
handle.execute("UPDATE usuarios SET usuario =?, contrasenia=?, id_tipo_usuario=?,
activo=? WHERE id_usuario=? ", pusuario, pcontrasenia, pid_tipo_usuario ,pactivo, pid_usuario);
});
return "USUARIO modifido correctamente";
}
catch(Exception e){
return e.toString();
}
}

/**
* Recupera la lista total de usuarios
* @return Lista de Usuarios
*/
@GET
@Path("/visualizacion")
@Produces({MediaType.APPLICATION_JSON})
public List<Usuarios> getUsuarios(){
Jdbi jdbi = new conectorBD().getJdbi();

List<Usuarios> usuarios = jdbi.withHandle(handle -> {


return handle.createQuery("SELECT * FROM usuarios WHERE activo ORDER BY usuario")
.mapToBean(Usuarios.class)
.list();
});

return usuarios;
}

/**
* Recupera la lista total de usuarios eliminados
* @return Lista de Usuarios eliminados
*/
@GET
@Path("/visualizacion/eliminados")
@Produces({MediaType.APPLICATION_JSON})
public List<Usuarios> getUsuariosEliminados(){
Jdbi jdbi = new conectorBD().getJdbi();

List<Usuarios> usuarios = jdbi.withHandle(handle -> {


return handle.createQuery("SELECT * FROM usuarios WHERE NOT activo ORDER BY
usuario")
.mapToBean(Usuarios.class)
.list();
});

return usuarios;
}

74
VENTAJAS Y DESVENTAJAS DE UTILIZAR JDBI

Antes de describir las ventajas y desventajas de utilizar Jdbi como medio de


acceso a los datos de una base datos, se debe enfatizar que estas son de
carácter subjetivo y reflejan el pensar de los autores de la presente
monografía.

VENTAJAS

• Jdbi ofrece un rendimiento (performance) superior, porque utiliza


instrucciones nativas de SQL para comunicarse con las diferentes
bases de datos.

• Jdbi ejecuta comandos nativos SQL directamente en el DBMS por


consiguiente no es necesario utilizar estrategias Lazy/Eager loading.

• Jdbi simplifica los mapeos o proyecciones, convirtiendo estos en:


sentencias SQL, que permiten explotar al máximo las funcionalidades
de la base de datos.

• Jdbi cuenta con menos anotaciones, como consecuencia es más


sencilla la elección de utilización de estas.

• En Jdbi solo se necesita agregar una dependencia y crear una


instancia para poder utilizar sus bondades.

75
• La API fluida de Jdbi hace que sea muy fácil inspeccionar los
métodos.

• La API fluida y la API declarativa de Jdbi aprovechan las expresiones


lambda y la programación funcional incluida en Java 8.

DESVENTAJAS

• En Jdbi el rendimiento (performance) en la manipulación y


recuperación de Datos depende directamente del rendimiento de la
DBMS que se utilice, provocando críticas a la aplicación desarrollada
en caso de que el DBMS tenga un bajo rendimiento.

• Al utilizar Jdbi la independencia de datos es menor, ya que las


instrucciones SQL dependen del Sistema Administrador de Base
Datos (DBMS) que se utilice.

• Los desarrolladores deben conocer de manera especializada el


lenguaje declarativo SQL.

• Jdbi tiene menos años en el mercado a comparación de frameworks


desarrollados con el estándar JPA considerados mucho más maduros,
razón por la cual no existe mucha documentación y soporte de la
misma.

76
CONCLUSIONES

• La monografía describe de forma eficiente y detallada a través de un


proyecto Maven el acceso a los datos de una base de datos utilizando
la librería Jdbi.

• Jdbi es una abstracción sobre JDBC.

• Jdbi presume que el desarrollador está profundamente conectado con


la base de datos y sus opciones de diseño e implementación.

• Jdbi no es un ORM como Hibernate, Jdbi utiliza un enfoque diferente


basado en funciones lambdas.

• Jdbi no contiene un mecanismo de almacenamiento en memoria


temporal (cache).

• Si se requiere una aplicación donde el rendimiento sea el factor más


importante es mejor utilizar Jdbi; pero por otra parte si el rendimiento
es algo que no es tan importante puede utilizarse JPA o Hibernate

77
RECOMENDACIONES

• La persistencia de datos no es la única forma de acceder a los datos


de una base datos, aunque esta sea la más popular de la década
actual.

• Jdbi es una alternativa que debe ser tomada en cuenta para el acceso
a los datos de una base datos.

• Ni la persistencia de datos, ni Jdbi remplazaran el criterio de: análisis y


diseño, tanto de la base de datos como de la aplicación que utilice
esta para obtener el rendimiento esperado.

• Si se desea utilizar la librería Jdbi se tiene que tener un conocimiento


pleno del lenguaje SQL, para facilitar la utilización de biblioteca Jdbi.

78
BIBLIOGRAFÍA

Danielsen, A. (11 de junio de 1999). The Evolution Of Data Models And


Approaches To Persistence In Database Systems. Obtenido de
https://www.fing.edu.uy/inco/grupos/csi/esp/Cursos/cursos_act/2000/D
AP_DisAvDB/documentacion/OO/Evol_DataModels.html

Eclipse Foundation. (2020). Jersey. Obtenido de https://eclipse-


ee4j.github.io/jersey/

Flores, M. G. (18 de agosto de 2013). SCRIBD. Obtenido de


https://www.scribd.com/document/161060631/SQL-Server-7

Jdbi. (2020). Java Database Interface 3. Obtenido de https://jdbi.org/

MakiGAS93. (16 de junio de 2016). Java: JPA + Hibernate – 16. ¡AYUDA!


Error Lazy Initialization (OneToMany). Obtenido de
https://www.youtube.com/watch?v=Q_9ICAkj1K4

Short, S. (2002). Building XML Web Services for the Microsoft NET Platform.
Microsft Press.

Tidwell, D., Snell, J., & Kulchenko, P. (2012). Programming Web Services
with SOAP. O'Reilly & Associates.

Tutorials Point. (s.f.). Tutorials Point. Obtenido de


https://www.tutorialspoint.com/jpa/jpa_orm_components.htm

79
Wikipedia. (junio de 200). Wikipedia. Obtenido de Open Datebase
Connectivity:
https://en.wikipedia.org/wiki/Open_Database_Connectivity

Wikipedia contributors. (17 de julio de 2020). Accounts receivable. Obtenido


de https://en.wikipedia.org/wiki/Accounts_receivable

Wikipedia contributors. (15 de julio de 2020). Jakarta Persistence. Obtenido


de https://en.wikipedia.org/wiki/Jakarta_Persistence

Wikipedia contributors. (23 de junio de 2020). Open Database Connectivity.


Obtenido de https://en.wikipedia.org/wiki/Open_Database_Connectivity

Wikipedia contributors. (18 de julio de 2020). PostgreSQL. Obtenido de


https://en.wikipedia.org/wiki/PostgreSQL

80
GLOSARIO DE TÉRMINOS

A
Antipatrón. patrón de diseño que conduce a una mala práctica o solución

O
Open Session in View es un antipatrón que consiste en crear una sesión y
vincularla a una solicitud (hilo) al comienzo de la cadena de procesamiento
de solicitudes, la cual se utiliza para consultar o actualizar la base de datos
durante todo el ciclo de vida de la solicitud.

T
Thread-safe, seguridad en hilos, se refiere a que múltiples hilos accedan a
los mismos datos compartidos y que la pieza compartida de datos sea
accedida por solamente un hilo en un momento dado.

U
UDDI (Descubrimiento, Descripción e Integración Universal) Lenguaje que
permite publicar, encontrar y usar los Servicios Web basados en XML. Es la
'Pagina Amarilla' de los servicios Web es decir un directorio para poder
encontrarlos. Puede ser accedido con un explorador en o programáticamente
ya que UDDI es también un servicio Web

V
Vararg Característica incluida desde la versión JDK 5 de Java, que simplifica
la creación de métodos que necesitan tomar un número variable de
argumentos

81
W
Web Service término que describe una colección de protocolos normalizados
de la industria y de servicios utilizados para facilitar el nivel de
interoperabilidad entre aplicaciones

X
XML (Lenguaje de Marcas eXtendido) Lenguaje universal para representar
los datos

DATOS PERSONALES DE LOS INTEGRANTES


Nombre: Vladimir Cabrera Arandia.
Teléfono: 72894875
Correo electrónico: vladimir_cabrera@hotmail.com , cabreravladimir@gmail.com

Nombre: Juan Gonzalo Rodriguez Arce.


Teléfono: 68143700
Correo electrónico: jgrodrigueza2016@gmail.com

82

También podría gustarte