Java JDBC: FIN + Emprendimiento
1
.gitignore
vendored
@ -13,3 +13,4 @@ bin/
|
||||
*.uml
|
||||
*.uxf
|
||||
*.umlcd
|
||||
target/
|
||||
|
@ -434,9 +434,9 @@ anteceden y preceden
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
||||
graph LR
|
||||
c1(cc1)-->c2(cc2)-->c1
|
||||
c2-->c3(cc3)-->c2
|
||||
c3-->c4(cc4)-->c3
|
||||
c1((cc1))-->c2((cc2))-->c1
|
||||
c2-->c3((cc3))-->c2
|
||||
c3-->c4((cc4))-->c3
|
||||
```
|
||||
|
||||
```java
|
||||
@ -605,18 +605,20 @@ public class TestRepasoArray {
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneX'}}}%%
|
||||
flowchart RL
|
||||
jln(java.lang.number)-->jld(java.lang.Double)--bytes-->8
|
||||
jln-->jlf(java.lang.Float)--bytes-->4
|
||||
jln-->jll(java.lang.Long)--bytes-->8
|
||||
jln-->jli(java.lang.Integer)--bytes-->4
|
||||
jln-->jls(java.lang.Short)--bytes-->2
|
||||
jln-->jlb(java.lang.Byte)--bytes-->1
|
||||
jln-->jlc(java.lang.Character)--bytes-->2
|
||||
jln-->jlbol(java.lang.Boolean)--bytes-->docs(JVM docs)
|
||||
flowchart LR
|
||||
jln(java.lang.number)-->jld(java.lang.Double)-->b8
|
||||
jln-->jlf(java.lang.Float)-->b4((4 bytes))
|
||||
jln-->jll(java.lang.Long)-->b8((8 bytes))
|
||||
jln-->jli(java.lang.Integer)-->b4
|
||||
jln-->jls(java.lang.Short)-->b2((2 bytes))
|
||||
jln-->jlb(java.lang.Byte)-->b1((1 byte))
|
||||
jln-->jlc(java.lang.Character)-->b2
|
||||
jln-->jlbol(java.lang.Boolean)-->docs{{JVM docs}}
|
||||
click docs "https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html#jvms-2.3.4" "Documentación Java" _blank
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
```java
|
||||
public static void main(String[] args) {
|
||||
Double numero_double = 33.0;
|
||||
|
@ -5,7 +5,7 @@
|
||||
- [Curso](https://app.aluracursos.com/course/lean-startup-metodo-eficaz-idea-negocio-empresa),
|
||||
Resumen [Lean Startup](./lean_startup.md)
|
||||
- [Curso](https://app.aluracursos.com/course/emprendimiento-idea-plan-negocios),
|
||||
Resumen [Emprendimiento]()
|
||||
Resumen [Emprendimiento](./emprendimiento.md)
|
||||
- [Curso](https://app.aluracursos.com/course/pitch-entrevistas-presentaciones-impactantes),
|
||||
Resumen [Pitch para entrevistas]()
|
||||
- Artículo
|
||||
|
BIN
009_emprendimiento/apple_lcm.webp
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
009_emprendimiento/bmc_template.jpg
Normal file
After Width: | Height: | Size: 122 KiB |
433
009_emprendimiento/emprendimiento.md
Normal file
@ -0,0 +1,433 @@
|
||||
# Emprendimiento
|
||||
|
||||
Curso
|
||||
[Emprendimiento](https://app.aluracursos.com/course/emprendimiento-idea-plan-negocios)
|
||||
|
||||
## De la idea al plan de negocios
|
||||
|
||||
### Agenda
|
||||
|
||||
- Pilares del emprendimiento
|
||||
- Qué es emprender
|
||||
- Características de la mentalidad del emprendedor
|
||||
- 3 fuerzas del negocio
|
||||
- Emprendedor
|
||||
- Oportunidades
|
||||
- Recursos
|
||||
- Ideas y oportunidades
|
||||
- Ideas vs oportunidades
|
||||
- Atractividad del mercado
|
||||
- Margen (precios y costes)
|
||||
- Diferenciación estratégica
|
||||
- Modelo de negocio
|
||||
- Propuesta de valor
|
||||
- Business Model Canvas
|
||||
- Plan de negocios
|
||||
- 9 elementos del plan
|
||||
|
||||
## Emprendimiento
|
||||
|
||||
> ***El proceso de crear algo nuevo asumiendo los riesgos y recompensas*** Robert
|
||||
Hisrich
|
||||
|
||||
### Mindset emprendedor
|
||||
|
||||
- Compromiso
|
||||
- Determinación
|
||||
- Perseverancia
|
||||
- Ambición (crecimiento)
|
||||
- Orientado a objetivos
|
||||
- Iniciativa y proactividad
|
||||
- Tolerancia a estés
|
||||
- Asumir riesgos calculados
|
||||
- Comparte riesgos
|
||||
- Buen manejo de errores y fracasos
|
||||
- Capacidad de aprendizaje
|
||||
- Construir equipos
|
||||
|
||||
### Mindset anti-emprendedor
|
||||
|
||||
- Sentimiento de invulnerabilidad
|
||||
- Infexibilidad
|
||||
- Antiautoridad
|
||||
- Impulsividad
|
||||
- Falta de control
|
||||
- Perfeccionismo
|
||||
- Creer saberlo todo
|
||||
- Querer trabajar poco
|
||||
|
||||
### Startup
|
||||
|
||||
- Nuevos mercados y productos
|
||||
- Tecnología
|
||||
- Escalable
|
||||
- Disruptiva
|
||||
- Incertidumbre
|
||||
- Debe probar su modelo de negocio
|
||||
- Puede transformase en ¿unicornio?
|
||||
|
||||
**StartUp vs Negocio LifeStyle**
|
||||
|
||||
### Intraemprendimiento
|
||||
|
||||
Emprender dentro de una corporación tiene oportunidades más restrictivas
|
||||
|
||||
- Representar intereses de un conjunto mayor
|
||||
- Core Business
|
||||
- Legado de la organización
|
||||
- Enfoque a corto plazo
|
||||
- Sin riesgos
|
||||
|
||||
Innovación radical como oportunidad de intraemprendimiento
|
||||
|
||||
En una startup todos son emprendedores
|
||||
|
||||
## Ejemplo Bytebank
|
||||
|
||||
- Una empresa - un producto
|
||||
- Tarjeta de crédito virtual 100%
|
||||
- Dos emprendedores
|
||||
- \+ 6 exfuncionarios del sector bancario
|
||||
- Compras online
|
||||
- Público objetivo: jóvenes de clase media
|
||||
- Autoservicio: Sin sucursales
|
||||
- Seguro contra extravío
|
||||
- Transparencia
|
||||
|
||||
----
|
||||
|
||||
## Pilares del emprendimiento
|
||||
|
||||
1. **Fundadores**
|
||||
- Emprendedor
|
||||
- Equipo de fundación
|
||||
- Experiencia y conocimiento
|
||||
- Autoridad
|
||||
- Gestión, habilidades y competencias
|
||||
- Actitud, tenacidad, osadía
|
||||
2. **Oportunidades**
|
||||
- Encontrar la oportunidad
|
||||
- Necesidad/problema real
|
||||
- Tamaño del mercado
|
||||
- Crecimiento
|
||||
- Momento correcto
|
||||
- Fuerzas (externas e internas)
|
||||
- Lucratividad y rentabilidad
|
||||
- Clientes 'ángeles' (pioneros)
|
||||
3. **Recursos**
|
||||
- Financieros
|
||||
- Tecnología
|
||||
- Producción
|
||||
- Personas
|
||||
- Sistemas
|
||||
- Consejeros/consultores
|
||||
- Controles de gestión
|
||||
|
||||
<br>
|
||||
|
||||
| Guia del emprendedor ||
|
||||
| - | - |
|
||||
| **¿Mis metas están definidas?** | Aspiraciones personales<br>Tamaño y sostenibilidad del negocio<br>Tolerancia a riesgos |
|
||||
| **¿Mi estrategia es correcta?** | Definida y clara<br>Lucrativa y con alto potencial de crecimiento<br>Durabilidad |
|
||||
| **¿Puedo ejecutar la estrategia?** | Recursos<br>Infraestructura<br>Papel del fundador |
|
||||
|
||||
<br>
|
||||
|
||||
| Modelo Flavio Augusto ||
|
||||
| - | - |
|
||||
| **¿Lo ves antes que todos?** | Como una información privilegiada<br>ej. equipo fútbol en USA |
|
||||
| **Coraje** | ¡Nadie te va a empujar, tienes que saltar! |
|
||||
| **Competencia** | Tú tienes que hacerlo realidad |
|
||||
|
||||
<br>
|
||||
|
||||
|Fórmula Daniel Wainmann |||
|
||||
| - | - | - |
|
||||
| Suerte | Talento | Estrategia |
|
||||
| **10%** | **10%** | **80%** |
|
||||
|
||||
<br>
|
||||
|
||||
> Referencias:
|
||||
> - The Questions Every Entrepreneurs Must Answer
|
||||
> *(Harvard Business Review) - Amar Bhide*
|
||||
> - Being a Sucessful Entrepreneur isn't Only About Having the Best Ideas
|
||||
> *(Harvard Business Review) - Andy Molinsky*
|
||||
> - Six Fundamentals Every Entrepreneur Needs
|
||||
> *(Harvard Business Review) - Bob Diener*
|
||||
> - TEDx Emprender e innovar en América Latina *Daniel Wainmann*
|
||||
|
||||
## Ideas y oportunidades
|
||||
|
||||
> **El problema debe ser más importante que la solución** Daniel Wainmann
|
||||
|
||||
|
||||
### Valor potencial
|
||||
|
||||
**`Problema` + `Solucion con diferencial` + `Emprendedor`**
|
||||
|
||||
..*"Las ideas son abuntantes, y las **soluciones escasas**"*..
|
||||
|
||||
### Atractivad del mercado
|
||||
|
||||
- Tamaño del mercado
|
||||
- ¿Cuántos clientes potenciales posee tu empresa?
|
||||
- ¿Cuánto genera esa industria actualmente en $?
|
||||
- ¿Tu producto es algo realmente necesario?
|
||||
- Compradores preparados
|
||||
- ¿Cuál es el nivel de preparación de tus compradores?
|
||||
- Homogeneidad de los compradores
|
||||
- ¿Las necesidades de su público son las mismas?
|
||||
- ¿Necesitas personalizar?
|
||||
- Verificar las reglas del segmento/area/rubro del país
|
||||
|
||||
### Margen precio costo
|
||||
|
||||
¿El margen líquido vale la pena?
|
||||
|
||||
| Rubro | Margen |
|
||||
| - | - |
|
||||
| Minería | 7% |
|
||||
| Aviación | 11% |
|
||||
| Farmacia | 15% |
|
||||
| Entretenimiento | 13% |
|
||||
| Seguros | 8% |
|
||||
| Energía | 4% |
|
||||
| Supermercado | 2% |
|
||||
| Cigarrillos | 28% |
|
||||
| Software | 12% |
|
||||
|
||||
| Tecnología | Margen |
|
||||
| - | - |
|
||||
| Baidu | 47.35% |
|
||||
| Adobe | 23% |
|
||||
| Microsoft | 21% |
|
||||
| AWS | 23% |
|
||||
| Apple | 24% |
|
||||
| Yahoo | 7% |
|
||||
|
||||
|
||||
### Escalabilidad e implementación
|
||||
|
||||
[<img src="./viab_graph.png" width="400"/>](./viab_graph.png)
|
||||
[<img src="./esca_graph.png" width="400"/>](./esca_graph.png)
|
||||
|
||||
### Recurrencia
|
||||
|
||||
Ejs. de servicios por subscripción: Gimnasios, Netflix, Spotify, etc.
|
||||
|
||||
### Competencia
|
||||
|
||||
- ¿Como se mueve el mercado en este momento?
|
||||
- ¿Cuales son los competidores y sustitutos?
|
||||
- Mirar fuera de la "mesa de juego"
|
||||
|
||||
### Diferencial
|
||||
|
||||
**¿Que te diferencia?** Ejemplo marcas de vehículos
|
||||
|
||||
- Precio
|
||||
- Volkswagen
|
||||
- Ford
|
||||
- Lujo
|
||||
- Mercedes-Benz
|
||||
- "Lujo y performance"
|
||||
- BMW
|
||||
- Calidad y precio
|
||||
- Nissan
|
||||
- Seguridad
|
||||
- Volvo
|
||||
- Performance y diseño
|
||||
- Ferrari
|
||||
- Tecnología
|
||||
- Tesla
|
||||
|
||||
### Facilidad de divulgación
|
||||
|
||||
¿De que forma se va a anunciar/comunicar con el cliente?
|
||||
|
||||
### Equipo de trabajo
|
||||
|
||||
Personas necesarias para que la empresa sea atractiva para inversionistas y
|
||||
consumidores
|
||||
|
||||
> [Four VCs on Evaluating Opportunities ](https://hbswk.hbs.edu/item/four-vcs-on-evaluating-opportunities)
|
||||
*(Harvard Business School) - Lauren Barley*
|
||||
[Creating a Culture of Entrepreneurship](https://hbswk.hbs.edu/item/skills-and-behaviors-that-make-entrepreneurs-successful)
|
||||
*Richard Patton*
|
||||
|
||||
## Propuesta de valor
|
||||
|
||||
- Necesidad: ¿Que necesidades resuelve tu producto o servicio?
|
||||
- Segmentos de clientes: Edad, clase social, género, intereses, etc.
|
||||
- Posicionamento
|
||||
- ¿Mercado nuevo o existente?
|
||||
- ¿Tendrá complementos?
|
||||
- ¿Cual es el MVP?
|
||||
- Precios/Categorías de precios
|
||||
- Precio o Costo para el cliente para cambiar a tu producto/servicio
|
||||
|
||||
### Tecnologías, operaciones y márgenes
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
|
||||
flowchart LR
|
||||
subgraph "Que actividades son necesarias para desarrollar el producto"
|
||||
MB["Marketing &
|
||||
Branding"]
|
||||
VN[Ventas]
|
||||
ET[Entregas]
|
||||
JR[Jurídico]
|
||||
CT[Contabilidad]
|
||||
DS[Desarrollo]
|
||||
RH["Recuros
|
||||
Humanos"]
|
||||
end
|
||||
```
|
||||
|
||||
Propiedad intelectual - ¿Hay algo que sea patentable?
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
|
||||
flowchart LR
|
||||
subgraph "Donde y como tu producto puede ser adquirido"
|
||||
VN[Teléfono]
|
||||
ET[Aplicación]
|
||||
JR[Página web]
|
||||
DS[Supermercados]
|
||||
RH[WhatsApp]
|
||||
CT["Redes
|
||||
Sociales"]
|
||||
end
|
||||
```
|
||||
|
||||
### Generar demanda
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
|
||||
flowchart LR
|
||||
subgraph "¿Como atraer clientes?"
|
||||
JR["Google adsense
|
||||
Social media ads"]
|
||||
VN[Outdoor]
|
||||
RH[Eventos]
|
||||
CT[Freemium]
|
||||
VR[Viralización]
|
||||
DS["Revistas
|
||||
Periodicos"]
|
||||
ET["Radio, TV
|
||||
podcast"]
|
||||
end
|
||||
```
|
||||
|
||||
### Customer Lifetime Value
|
||||
|
||||
¿Cual es el CVL esperado? Valor del tiempo de vida del cliente
|
||||
|
||||
- **CLV** `=` Valor medio de compras de un cliente `x` compras por año `x` años de permanencia
|
||||
|
||||
¿Cual es el costo de adquisición del cliente (CAC)?
|
||||
|
||||
- **CAC** `=` Gastos `/` Nro. de clientes nuevos
|
||||
|
||||
¿Existe una oportunidad de *Upsell*?
|
||||
|
||||
Recurrencia, subscripción
|
||||
|
||||
### Margen
|
||||
|
||||
[<img src="./punto_muerto.png" width="400"/>](./punto_muerto.png)
|
||||
|
||||
- Margen de ganancia
|
||||
- Costos fijos
|
||||
- Punto de equilibrio (*breakeven*)
|
||||
|
||||
### Ritmo de crecimiento
|
||||
|
||||
¿El mercado está parando o en crecimiento, a que ritmo?
|
||||
|
||||
### Capital de giro
|
||||
|
||||
¿Cual es la necesidad de capital de giro del negocio?
|
||||
|
||||
## Business Model Canvas
|
||||
|
||||
[<img src="./bmc_template.jpg" width="100%"/>](./bmc_template.jpg)
|
||||
|
||||
### Ejms. BMC
|
||||
|
||||
[<img src="./tesla_lcm.webp" width="100%"/>](./tesla_lcm.webp)
|
||||
[<img src="./google_lcm.webp" width="100%"/>](./google_lcm.webp)
|
||||
[<img src="./apple_lcm.webp" width="100%"/>](./apple_lcm.webp)
|
||||
[<img src="./skype_lcm.webp" width="100%"/>](./skype_lcm.webp)
|
||||
[<img src="./facebook_lcm.webp" width="100%"/>](./facebook_lcm.webp)
|
||||
|
||||
## Plan de negocio
|
||||
|
||||
*.."La idea parecía fantástica, pero los números dicen otra cosa"..*
|
||||
|
||||
### Resumen ejecutivo
|
||||
|
||||
La oportunidad de llamar la atencion del inversor
|
||||
|
||||
- Conceptp del negocio
|
||||
- UVP (Unique Value Proposition)
|
||||
- Inversion necesaria
|
||||
- Clientes y mercado
|
||||
|
||||
### Producto o servicio
|
||||
|
||||
- Funcionalidades
|
||||
- Público objetivo
|
||||
- Fuentes de ingresos
|
||||
- Estado actual de desarrollo
|
||||
- ¿Existe algo similar en otro país o mercado?
|
||||
- ¿Como fidelizar al cliente?
|
||||
|
||||
### Equipo
|
||||
|
||||
- ¿Quienes son los fundadores?
|
||||
- Capacidad de cada fundador par el éxito
|
||||
- División de responsbilidades
|
||||
|
||||
### Mercado
|
||||
|
||||
- Tamaño del mercado
|
||||
- Potencial de crecimiento
|
||||
- Competencia
|
||||
- Puntos fuertes y débiles
|
||||
|
||||
### Marketing y ventas
|
||||
|
||||
- ¿Como promover?
|
||||
- ¿Como distribuir?
|
||||
- ¿Como fijar el precio?
|
||||
|
||||
### Organización
|
||||
|
||||
- Construcción de equipos
|
||||
- Plan de contratación
|
||||
- Tercerización
|
||||
- Aliados
|
||||
- Canales de ventas
|
||||
|
||||
### Cronograma
|
||||
|
||||
- Responsables
|
||||
- Plazos
|
||||
- Hitos (*milestones*)
|
||||
|
||||
### Riesgos
|
||||
|
||||
- El mejor y el peor escenario
|
||||
- Principales riesgos
|
||||
- Como mitigar los riesgos
|
||||
|
||||
### Finazas
|
||||
|
||||
- Estado de resultados
|
||||
- Flujo de caja
|
||||
- Tasación
|
||||
- Balance
|
||||
- Fuentes de financiación
|
||||
|
1
009_emprendimiento/esca-graph.svg
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
009_emprendimiento/esca_graph.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
009_emprendimiento/facebook_lcm.webp
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
009_emprendimiento/google_lcm.webp
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
009_emprendimiento/lean_canvas_model_dark.webp
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
009_emprendimiento/lean_canvas_model_template.webp
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
009_emprendimiento/punto_muerto.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
009_emprendimiento/skype_lcm.webp
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
009_emprendimiento/tesla_lcm.webp
Normal file
After Width: | Height: | Size: 57 KiB |
1
009_emprendimiento/viab-graph.svg
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
009_emprendimiento/viab_graph.png
Normal file
After Width: | Height: | Size: 14 KiB |
@ -4,4 +4,6 @@ Tablero en [trello](https://trello.com/b/gWJsG18e/g5-formaci%C3%B3n-spring-boot)
|
||||
|
||||
- [Curso](https://app.aluracursos.com/course/introduccion-sql-mysql-manipule-consulte-datos)
|
||||
Java y [bases de datos](./base_de_datos.md)
|
||||
|
||||
- Lectura [JDBC](https://www.aluracursos.com/blog/conociendo-el-jdbc)
|
||||
- [Curso](https://app.aluracursos.com/course/java-jdbc-trabajando-base-datos)
|
||||
Java y [JDBC](./jdbc.md)
|
||||
|
@ -292,7 +292,7 @@ realizado su primera compra.
|
||||
|
||||
```sql
|
||||
-- show databases;
|
||||
use jugos;
|
||||
USE jugos;
|
||||
CREATE TABLE cliente(
|
||||
dni VARCHAR(20),
|
||||
nombre VARCHAR(150),
|
||||
@ -317,7 +317,7 @@ CREATE TABLE cliente(
|
||||
#### Creación de tabla **`vendedor`**
|
||||
|
||||
```sql
|
||||
use jugos;
|
||||
USE jugos;
|
||||
CREATE TABLE vendedor(
|
||||
matricula VARCHAR(4),
|
||||
nombre VARCHAR(100),
|
||||
@ -328,7 +328,7 @@ CREATE TABLE vendedor(
|
||||
#### Elimnar tabla
|
||||
|
||||
```sql
|
||||
use jugos;
|
||||
USE jugos;
|
||||
-- CREATE TABLE vendedor2(
|
||||
-- matricula VARCHAR(4),
|
||||
-- nombre VARCHAR(100),
|
||||
|
42
010_spring_boot/java_jdbc/control-de-stock/pom.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.alura</groupId>
|
||||
<artifactId>control-de-stock</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>Control de Stock</name>
|
||||
<description>Proyecto para trabajar con bases de datos con JDBC</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.33</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.5.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>mchange-commons-java</artifactId>
|
||||
<version>0.2.20</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.11.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,14 @@
|
||||
package com.alura.jdbc;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import com.alura.jdbc.view.ControlDeStockFrame;
|
||||
|
||||
public class ControlDeStockMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
ControlDeStockFrame produtoCategoriaFrame = new ControlDeStockFrame();
|
||||
produtoCategoriaFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.alura.jdbc.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alura.jdbc.dao.CategoriaDAO;
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
import com.alura.jdbc.modelo.Categoria;
|
||||
|
||||
public class CategoriaController {
|
||||
|
||||
private CategoriaDAO categoriaDAO;
|
||||
|
||||
public CategoriaController() {
|
||||
var factory = new ConnectionFactory();
|
||||
this.categoriaDAO = new CategoriaDAO(factory.recuperaConexion());
|
||||
}
|
||||
|
||||
public List<Categoria> listar() {
|
||||
return categoriaDAO.listar();
|
||||
}
|
||||
|
||||
public List<Categoria> cargaReporte() {
|
||||
return this.categoriaDAO.listarConProductos();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.alura.jdbc.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alura.jdbc.dao.ProductoDAO;
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
import com.alura.jdbc.modelo.Categoria;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class ProductoController {
|
||||
|
||||
private ProductoDAO productoDAO;
|
||||
|
||||
public ProductoController() {
|
||||
this.productoDAO = new ProductoDAO(new ConnectionFactory().recuperaConexion());
|
||||
}
|
||||
|
||||
public int modificar(Producto producto) {
|
||||
return productoDAO.modificar(producto);
|
||||
}
|
||||
|
||||
public int eliminar(Integer id) {
|
||||
return productoDAO.eliminar(id);
|
||||
}
|
||||
|
||||
public List<Producto> listar() {
|
||||
return productoDAO.listar();
|
||||
}
|
||||
|
||||
public List<Producto> listar(Categoria categoria) {
|
||||
return productoDAO.listar(categoria.getId());
|
||||
}
|
||||
|
||||
public void guardar(Producto producto, Integer categoriaId) {
|
||||
producto.setCategoriaId(categoriaId);
|
||||
productoDAO.guardar(producto);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
package com.alura.jdbc.dao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.alura.jdbc.modelo.Categoria;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class CategoriaDAO {
|
||||
private final Connection con;
|
||||
|
||||
public CategoriaDAO(Connection conexion) {
|
||||
this.con = conexion;
|
||||
}
|
||||
|
||||
public void guardar(Categoria categoria) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"INSERT INTO categoria(nombre) VALUES(?)",
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
try (statement) {
|
||||
ejecutaRegistro(categoria, statement);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ejecutaRegistro(Categoria categoria, PreparedStatement statement)
|
||||
throws SQLException {
|
||||
statement.setString(1, categoria.getNombre());
|
||||
statement.execute();
|
||||
final ResultSet resultSet = statement.getGeneratedKeys();
|
||||
try (resultSet) {
|
||||
while (resultSet.next()) {
|
||||
categoria.setId(resultSet.getInt(1));
|
||||
System.out.println(String.format("Categoria agregada %s: ", categoria));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Categoria> listar() {
|
||||
List<Categoria> resultado = new ArrayList<>();
|
||||
final String query = "SELECT ID, NOMBRE FROM categoria;";
|
||||
System.out.println(query);
|
||||
try {
|
||||
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
ResultSet resultSet = statement.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
Categoria fila = new Categoria(
|
||||
resultSet.getInt("ID"),
|
||||
resultSet.getString("NOMBRE")
|
||||
);
|
||||
resultado.add(fila);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int modificar(Categoria categoria) {
|
||||
try {
|
||||
final String query = "UPDATE categoria SET NOMBRE=? WHERE ID=?;";
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.setString(1, categoria.getNombre());
|
||||
statement.setInt(2, categoria.getId());
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int eliminar(Integer id) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement("DELETE FROM categoria WHERE ID=?;");
|
||||
try (statement) {
|
||||
statement.setInt(1, id);
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Categoria> listarConProductos() {
|
||||
List<Categoria> resultado = new ArrayList<>();
|
||||
final String query = "SELECT C.ID, C.NOMBRE, P.ID, P.NOMBRE, P.CANTIDAD FROM categoria C "
|
||||
+ "INNER JOIN producto P ON C.ID = P.CATEGORIA_ID ";
|
||||
System.out.println(query);
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
final ResultSet resultSet = statement.getResultSet();
|
||||
try (resultSet){
|
||||
while (resultSet.next()) {
|
||||
Integer categoriaId = resultSet.getInt("C.ID");
|
||||
String categoriaNombre = resultSet.getString("C.NOMBRE");
|
||||
var categoria = resultado
|
||||
.stream()
|
||||
.filter(cat -> cat.getId().equals(categoriaId))
|
||||
.findAny().orElseGet(() -> {
|
||||
Categoria cat = new Categoria(categoriaId, categoriaNombre);
|
||||
resultado.add(cat);
|
||||
return cat;
|
||||
});
|
||||
Producto producto = new Producto(resultSet.getInt("P.ID"),
|
||||
resultSet.getString("P.NOMBRE"),
|
||||
resultSet.getInt("P.CANTIDAD"));
|
||||
categoria.agregar(producto);
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,144 @@
|
||||
package com.alura.jdbc.dao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class ProductoDAO {
|
||||
private final Connection con;
|
||||
|
||||
public ProductoDAO(Connection conexion) {
|
||||
this.con = conexion;
|
||||
}
|
||||
|
||||
public void guardar(Producto producto) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"INSERT INTO producto(nombre, descripcion, cantidad, categoria_id) VALUES(?,?,?,?)",
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
try (statement) {
|
||||
ejecutaRegistro(producto, statement);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ejecutaRegistro(Producto producto, PreparedStatement statement)
|
||||
throws SQLException {
|
||||
statement.setString(1, producto.getNombre());
|
||||
statement.setString(2, producto.getDescripcion());
|
||||
statement.setInt(3, producto.getCantidad());
|
||||
statement.setInt(4, producto.getCategoriaId());
|
||||
statement.execute();
|
||||
final ResultSet resultSet = statement.getGeneratedKeys();
|
||||
try (resultSet) {
|
||||
while (resultSet.next()) {
|
||||
producto.setId(resultSet.getInt(1));
|
||||
System.out.println(String.format("Producto insertado %s: ", producto));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Producto> listar() {
|
||||
List<Producto> resultado = new ArrayList<>();
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"SELECT ID, NOMBRE, DESCRIPCION, CANTIDAD, CATEGORIA_ID FROM producto;");
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
ResultSet resultSet = statement.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
Producto fila = new Producto(
|
||||
resultSet.getInt("ID"),
|
||||
resultSet.getString("NOMBRE"),
|
||||
resultSet.getString("DESCRIPCION"),
|
||||
resultSet.getInt("CANTIDAD"),
|
||||
resultSet.getInt("CATEGORIA_ID")
|
||||
);
|
||||
resultado.add(fila);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int modificar(Producto producto) {
|
||||
String query = "UPDATE producto SET NOMBRE=?, DESCRIPCION=?, CANTIDAD=? ";
|
||||
if (producto.getCategoriaId() != null) {
|
||||
query += ", CATEGORIA_ID=? WHERE ID=?;";
|
||||
} else {
|
||||
query += " WHERE ID=?;";
|
||||
}
|
||||
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.setString(1, producto.getNombre());
|
||||
statement.setString(2, producto.getDescripcion());
|
||||
statement.setInt(3, producto.getCantidad());
|
||||
if (producto.getCategoriaId() != null) {
|
||||
statement.setInt(4, producto.getCategoriaId());
|
||||
statement.setInt(5, producto.getId());
|
||||
} else {
|
||||
statement.setInt(4, producto.getId());
|
||||
}
|
||||
//System.out.println(statement.toString());
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int eliminar(Integer id) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement("DELETE FROM producto WHERE ID=?;");
|
||||
try (statement) {
|
||||
statement.setInt(1, id);
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<Producto> listar(Integer id) {
|
||||
List<Producto> resultado = new ArrayList<>();
|
||||
final String query = "SELECT ID, NOMBRE, DESCRIPCION, CANTIDAD, CATEGORIA_ID FROM producto WHERE categoria_id=?;";
|
||||
//System.out.println(query);
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
statement.setInt(1, id);
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
ResultSet resultSet = statement.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
Producto fila = new Producto(
|
||||
resultSet.getInt("ID"),
|
||||
resultSet.getString("NOMBRE"),
|
||||
resultSet.getString("DESCRIPCION"),
|
||||
resultSet.getInt("CANTIDAD"),
|
||||
resultSet.getInt("CATEGORIA_ID")
|
||||
);
|
||||
resultado.add(fila);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.alura.jdbc.factory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||
|
||||
public class ConnectionFactory {
|
||||
|
||||
private final static String driver = "jdbc:mysql://";
|
||||
private final static String dbaddr = "192.168.0.8:3306/";
|
||||
private final static String params = "?useTimeZone=true&serverTimeZone=UTC";
|
||||
private final static String dbname = "control_de_stock";
|
||||
private final static String dburl = driver+dbaddr+dbname+params;
|
||||
private final static String dbuser = "alura";
|
||||
private final static String dbpass = "alura";
|
||||
|
||||
private DataSource datasource;
|
||||
|
||||
public ConnectionFactory() {
|
||||
var pooledDataSource = new ComboPooledDataSource();
|
||||
pooledDataSource.setJdbcUrl(dburl);
|
||||
pooledDataSource.setUser(dbuser);
|
||||
pooledDataSource.setPassword(dbpass);
|
||||
pooledDataSource.setMaxPoolSize(10);
|
||||
this.datasource = pooledDataSource;
|
||||
}
|
||||
|
||||
public Connection recuperaConexion() {
|
||||
//return DriverManager.getConnection(dburl, dbuser, dbpass);
|
||||
try {
|
||||
return this.datasource.getConnection();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package com.alura.jdbc.modelo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Categoria {
|
||||
|
||||
private Integer id;
|
||||
private String nombre;
|
||||
private List<Producto> productos;
|
||||
|
||||
public Categoria(int id, String nombre) {
|
||||
this.id = id;
|
||||
this.nombre = nombre;
|
||||
}
|
||||
|
||||
public String getNombre() {
|
||||
return this.nombre;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.getNombre();
|
||||
}
|
||||
|
||||
public void agregar(Producto producto) {
|
||||
if (this.productos == null) {
|
||||
this.productos = new ArrayList<>();
|
||||
}
|
||||
this.productos.add(producto);
|
||||
}
|
||||
|
||||
public List<Producto> getProductos() {
|
||||
return this.productos;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
package com.alura.jdbc.modelo;
|
||||
|
||||
public class Producto {
|
||||
private Integer id;
|
||||
private String nombre;
|
||||
private String descripcion;
|
||||
private Integer cantidad;
|
||||
private Integer categoriaId;
|
||||
|
||||
public Producto(String nombre, String descripcion, Integer cantidad) {
|
||||
this.nombre = nombre;
|
||||
this.descripcion = descripcion;
|
||||
this.cantidad = cantidad;
|
||||
}
|
||||
|
||||
public Producto(Integer id, String nombre, String descripcion, Integer cantidad) {
|
||||
this.id = id;
|
||||
this.nombre = nombre;
|
||||
this.descripcion = descripcion;
|
||||
this.cantidad = cantidad;
|
||||
}
|
||||
|
||||
public Producto(Integer id, String nombre, String descripcion, Integer cantidad, Integer categoriaId) {
|
||||
this.id = id;
|
||||
this.nombre = nombre;
|
||||
this.descripcion = descripcion;
|
||||
this.cantidad = cantidad;
|
||||
this.categoriaId = categoriaId;
|
||||
}
|
||||
|
||||
public Producto(Integer id, String nombre, Integer cantidad) {
|
||||
this.id = id;
|
||||
this.nombre = nombre;
|
||||
this.cantidad = cantidad;
|
||||
}
|
||||
|
||||
public String getNombre() {
|
||||
return this.nombre;
|
||||
}
|
||||
|
||||
public String getDescripcion() {
|
||||
return this.descripcion;
|
||||
}
|
||||
|
||||
public int getCantidad() {
|
||||
return this.cantidad;
|
||||
}
|
||||
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{id: %d, nombre: %s, descripción: %s, cantidad: %d, categoria: %d}",
|
||||
this.id, this.nombre, this.descripcion, this.cantidad, this.categoriaId);
|
||||
}
|
||||
|
||||
public void setCategoriaId(Integer categoriaId) {
|
||||
this.categoriaId = categoriaId;
|
||||
}
|
||||
|
||||
public Integer getCategoriaId() {
|
||||
return this.categoriaId;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.alura.jdbc.pruebas;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
|
||||
public class PruebaConexion {
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
Connection con = new ConnectionFactory().recuperaConexion();
|
||||
System.out.println("Cerrando conexión");
|
||||
con.close();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.alura.jdbc.pruebas;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
|
||||
public class PruebaDelete {
|
||||
public static void main(String[] args) throws SQLException {
|
||||
Connection con = new ConnectionFactory().recuperaConexion();
|
||||
Statement stmnt = con.createStatement();
|
||||
stmnt.execute("DELETE FROM producto WHERE ID=99");
|
||||
System.out.println(stmnt.getUpdateCount());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.alura.jdbc.pruebas;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
|
||||
public class PruebaPoolDeConexiones {
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
ConnectionFactory connectionFactory = new ConnectionFactory();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
@SuppressWarnings("unused")
|
||||
Connection con = connectionFactory.recuperaConexion();
|
||||
System.out.println("Abriendo conexión nro: "+(i+1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,285 @@
|
||||
package com.alura.jdbc.view;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Container;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
import com.alura.jdbc.controller.CategoriaController;
|
||||
import com.alura.jdbc.controller.ProductoController;
|
||||
import com.alura.jdbc.modelo.Categoria;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class ControlDeStockFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JLabel labelNombre, labelDescripcion, labelCantidad, labelCategoria;
|
||||
private JTextField textoNombre, textoDescripcion, textoCantidad;
|
||||
private JComboBox<Categoria> comboCategoria;
|
||||
private JButton botonGuardar, botonModificar, botonLimpiar, botonEliminar, botonReporte;
|
||||
private JTable tabla;
|
||||
private DefaultTableModel modelo;
|
||||
private ProductoController productoController;
|
||||
private CategoriaController categoriaController;
|
||||
|
||||
public ControlDeStockFrame() {
|
||||
super("Productos");
|
||||
|
||||
this.categoriaController = new CategoriaController();
|
||||
this.productoController = new ProductoController();
|
||||
|
||||
Container container = getContentPane();
|
||||
setLayout(null);
|
||||
|
||||
configurarCamposDelFormulario(container);
|
||||
|
||||
configurarTablaDeContenido(container);
|
||||
|
||||
configurarAccionesDelFormulario();
|
||||
}
|
||||
|
||||
private void configurarTablaDeContenido(Container container) {
|
||||
tabla = new JTable();
|
||||
|
||||
modelo = (DefaultTableModel) tabla.getModel();
|
||||
modelo.addColumn("Identificador del Producto");
|
||||
modelo.addColumn("Nombre del Producto");
|
||||
modelo.addColumn("Descripción del Producto");
|
||||
modelo.addColumn("Cantidad");
|
||||
|
||||
cargarTabla();
|
||||
|
||||
tabla.setBounds(10, 205, 760, 280);
|
||||
|
||||
botonEliminar = new JButton("Eliminar");
|
||||
botonModificar = new JButton("Modificar");
|
||||
botonReporte = new JButton("Ver Reporte");
|
||||
botonEliminar.setBounds(10, 500, 80, 20);
|
||||
botonModificar.setBounds(100, 500, 80, 20);
|
||||
botonReporte.setBounds(190, 500, 80, 20);
|
||||
|
||||
container.add(tabla);
|
||||
container.add(botonEliminar);
|
||||
container.add(botonModificar);
|
||||
container.add(botonReporte);
|
||||
|
||||
setSize(800, 600);
|
||||
setVisible(true);
|
||||
setLocationRelativeTo(null);
|
||||
}
|
||||
|
||||
private void configurarCamposDelFormulario(Container container) {
|
||||
labelNombre = new JLabel("Nombre del Producto");
|
||||
labelDescripcion = new JLabel("Descripción del Producto");
|
||||
labelCantidad = new JLabel("Cantidad");
|
||||
labelCategoria = new JLabel("Categoría del Producto");
|
||||
|
||||
labelNombre.setBounds(10, 10, 240, 15);
|
||||
labelDescripcion.setBounds(10, 50, 240, 15);
|
||||
labelCantidad.setBounds(10, 90, 240, 15);
|
||||
labelCategoria.setBounds(10, 130, 240, 15);
|
||||
|
||||
labelNombre.setForeground(Color.BLACK);
|
||||
labelDescripcion.setForeground(Color.BLACK);
|
||||
labelCategoria.setForeground(Color.BLACK);
|
||||
|
||||
textoNombre = new JTextField();
|
||||
textoDescripcion = new JTextField();
|
||||
textoCantidad = new JTextField();
|
||||
comboCategoria = new JComboBox<>();
|
||||
comboCategoria.addItem(new Categoria(0, "Elige una categoría"));
|
||||
|
||||
var categorias = this.categoriaController.listar();
|
||||
categorias.forEach(categoria -> comboCategoria.addItem(categoria));
|
||||
|
||||
textoNombre.setBounds(10, 25, 265, 20);
|
||||
textoDescripcion.setBounds(10, 65, 265, 20);
|
||||
textoCantidad.setBounds(10, 105, 265, 20);
|
||||
comboCategoria.setBounds(10, 145, 265, 20);
|
||||
|
||||
botonGuardar = new JButton("Guardar");
|
||||
botonLimpiar = new JButton("Limpiar");
|
||||
botonGuardar.setBounds(10, 175, 80, 20);
|
||||
botonLimpiar.setBounds(100, 175, 80, 20);
|
||||
|
||||
container.add(labelNombre);
|
||||
container.add(labelDescripcion);
|
||||
container.add(labelCantidad);
|
||||
container.add(labelCategoria);
|
||||
container.add(textoNombre);
|
||||
container.add(textoDescripcion);
|
||||
container.add(textoCantidad);
|
||||
container.add(comboCategoria);
|
||||
container.add(botonGuardar);
|
||||
container.add(botonLimpiar);
|
||||
}
|
||||
|
||||
private void configurarAccionesDelFormulario() {
|
||||
botonGuardar.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
guardar();
|
||||
limpiarTabla();
|
||||
cargarTabla();
|
||||
}
|
||||
});
|
||||
|
||||
botonLimpiar.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
limpiarFormulario();
|
||||
}
|
||||
});
|
||||
|
||||
botonEliminar.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
eliminar();
|
||||
limpiarTabla();
|
||||
cargarTabla();
|
||||
}
|
||||
});
|
||||
|
||||
botonModificar.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
modificar();
|
||||
limpiarTabla();
|
||||
cargarTabla();
|
||||
}
|
||||
});
|
||||
|
||||
botonReporte.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
abrirReporte();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void abrirReporte() {
|
||||
new ReporteFrame(this);
|
||||
}
|
||||
|
||||
private void limpiarTabla() {
|
||||
modelo.getDataVector().clear();
|
||||
}
|
||||
|
||||
private boolean tieneFilaElegida() {
|
||||
return tabla.getSelectedRowCount() == 0 || tabla.getSelectedColumnCount() == 0;
|
||||
}
|
||||
|
||||
private boolean tieneCatElegida() {
|
||||
return !(comboCategoria.getSelectedItem().toString().equals(comboCategoria.getItemAt(0).toString()));
|
||||
}
|
||||
|
||||
private void modificar() {
|
||||
if (tieneFilaElegida()) {
|
||||
JOptionPane.showMessageDialog(this, "Por favor, elije un item");
|
||||
return;
|
||||
}
|
||||
if (tieneCatElegida()) {
|
||||
Optional.ofNullable(modelo.getValueAt(tabla.getSelectedRow(), tabla.getSelectedColumn()))
|
||||
.ifPresentOrElse(fila -> {
|
||||
Producto producto = new Producto(
|
||||
Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 0).toString()),
|
||||
(String) modelo.getValueAt(tabla.getSelectedRow(), 1),
|
||||
(String) modelo.getValueAt(tabla.getSelectedRow(), 2),
|
||||
Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 3).toString()),
|
||||
(Integer) ((Categoria) comboCategoria.getSelectedItem()).getId());
|
||||
int cantidadActualizada;
|
||||
cantidadActualizada = this.productoController.modificar(producto);
|
||||
JOptionPane.showMessageDialog(this, cantidadActualizada+" Item actualizado con éxito!");
|
||||
}, () -> JOptionPane.showMessageDialog(this, "Por favor, elije un item"));
|
||||
} else {
|
||||
Optional.ofNullable(modelo.getValueAt(tabla.getSelectedRow(), tabla.getSelectedColumn()))
|
||||
.ifPresentOrElse(fila -> {
|
||||
var producto = new Producto(
|
||||
Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 0).toString()),
|
||||
(String) modelo.getValueAt(tabla.getSelectedRow(), 1),
|
||||
(String) modelo.getValueAt(tabla.getSelectedRow(), 2),
|
||||
Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 3).toString()));
|
||||
int cantidadActualizada;
|
||||
cantidadActualizada = this.productoController.modificar(producto);
|
||||
JOptionPane.showMessageDialog(this, cantidadActualizada+" Item actualizado con éxito!");
|
||||
}, () -> JOptionPane.showMessageDialog(this, "Por favor, elije un item"));
|
||||
}
|
||||
}
|
||||
|
||||
private void eliminar() {
|
||||
if (tieneFilaElegida()) {
|
||||
JOptionPane.showMessageDialog(this, "Por favor, elije un item");
|
||||
return;
|
||||
}
|
||||
|
||||
Optional.ofNullable(modelo.getValueAt(tabla.getSelectedRow(), tabla.getSelectedColumn()))
|
||||
.ifPresentOrElse(fila -> {
|
||||
Integer id = Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 0).toString());
|
||||
|
||||
int cantidadEliminada;
|
||||
cantidadEliminada = this.productoController.eliminar(id);
|
||||
modelo.removeRow(tabla.getSelectedRow());
|
||||
|
||||
JOptionPane.showMessageDialog(this, cantidadEliminada+" Item eliminado con éxito!");
|
||||
}, () -> JOptionPane.showMessageDialog(this, "Por favor, elije un item"));
|
||||
}
|
||||
|
||||
private void cargarTabla() {
|
||||
var productos = this.productoController.listar();
|
||||
productos.forEach(producto -> modelo.addRow(
|
||||
new Object[] {
|
||||
producto.getId(),
|
||||
producto.getNombre(),
|
||||
producto.getDescripcion(),
|
||||
producto.getCantidad(),
|
||||
producto.getCategoriaId()
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void guardar() {
|
||||
if (textoNombre.getText().isBlank() || textoDescripcion.getText().isBlank()) {
|
||||
JOptionPane.showMessageDialog(this, "Los campos Nombre y Descripción son requeridos.");
|
||||
return;
|
||||
}
|
||||
|
||||
Integer cantidadInt;
|
||||
|
||||
try {
|
||||
cantidadInt = Integer.parseInt(textoCantidad.getText());
|
||||
} catch (NumberFormatException e) {
|
||||
JOptionPane.showMessageDialog(this, String
|
||||
.format("El campo cantidad debe ser numérico dentro del rango %d y %d.", 0, Integer.MAX_VALUE));
|
||||
return;
|
||||
}
|
||||
|
||||
//var producto = new HashMap<String,String>();
|
||||
//producto.put("NOMBRE",textoNombre.getText());
|
||||
//producto.put("DESCRIPCION", textoDescripcion.getText());
|
||||
//producto.put("CANTIDAD", String.valueOf(cantidadInt));
|
||||
var producto = new Producto(textoNombre.getText(),
|
||||
textoDescripcion.getText(),
|
||||
cantidadInt);
|
||||
|
||||
var categoria = (Categoria) comboCategoria.getSelectedItem();
|
||||
|
||||
this.productoController.guardar(producto, categoria.getId());
|
||||
JOptionPane.showMessageDialog(this, "Registrado con éxito!");
|
||||
this.limpiarFormulario();
|
||||
}
|
||||
|
||||
private void limpiarFormulario() {
|
||||
this.textoNombre.setText("");
|
||||
this.textoDescripcion.setText("");
|
||||
this.textoCantidad.setText("");
|
||||
this.comboCategoria.setSelectedIndex(0);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
package com.alura.jdbc.view;
|
||||
|
||||
import java.awt.Container;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
|
||||
import com.alura.jdbc.controller.CategoriaController;
|
||||
//import com.alura.jdbc.controller.ProductoController;
|
||||
|
||||
public class ReporteFrame extends JFrame {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private JTable tablaReporte;
|
||||
private DefaultTableModel modelo;
|
||||
|
||||
private CategoriaController categoriaController;
|
||||
//private ProductoController productoController;
|
||||
|
||||
public ReporteFrame(ControlDeStockFrame controlDeStockFrame) {
|
||||
super("Reporte de produtos del stock");
|
||||
|
||||
this.categoriaController = new CategoriaController();
|
||||
//this.productoController = new ProductoController();
|
||||
|
||||
Container container = getContentPane();
|
||||
setLayout(null);
|
||||
|
||||
tablaReporte = new JTable();
|
||||
tablaReporte.setBounds(0, 0, 600, 400);
|
||||
container.add(tablaReporte);
|
||||
|
||||
modelo = (DefaultTableModel) tablaReporte.getModel();
|
||||
modelo.addColumn("");
|
||||
modelo.addColumn("");
|
||||
modelo.addColumn("");
|
||||
modelo.addColumn("");
|
||||
|
||||
cargaReporte();
|
||||
|
||||
setSize(600, 400);
|
||||
setVisible(true);
|
||||
setLocationRelativeTo(controlDeStockFrame);
|
||||
}
|
||||
|
||||
private void cargaReporte() {
|
||||
var contenido = categoriaController.cargaReporte();
|
||||
contenido.forEach(categoria -> {
|
||||
modelo.addRow(new Object[] { categoria.getId(),
|
||||
categoria.getNombre(),
|
||||
"Artículo", "Stock" });
|
||||
var productos = categoria.getProductos();
|
||||
productos.forEach(producto ->
|
||||
modelo.addRow(new Object[] { "",
|
||||
producto.getId(),
|
||||
producto.getNombre(),
|
||||
producto.getCantidad() }
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
package com.alura.tests;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class PruebaConexion {
|
||||
|
||||
private final static String driver = "jdbc:mysql://";
|
||||
private final static String dbaddr = "192.168.0.8:3306/";
|
||||
private final static String params = "?useTimeZone=true&serverTimeZone=UTC";
|
||||
private final static String dbname = "control_de_stock";
|
||||
private final static String dburl = driver+dbaddr+dbname+params;
|
||||
private final static String dbuser = "alura";
|
||||
private final static String dbpass = "alura";
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
System.out.println("hola");
|
||||
Connection con = DriverManager.getConnection(dburl, dbuser, dbpass);
|
||||
con.close();
|
||||
System.out.println("chao");
|
||||
}
|
||||
|
||||
}
|
677
010_spring_boot/jdbc.md
Normal file
@ -0,0 +1,677 @@
|
||||
# JDBC
|
||||
|
||||
```sh
|
||||
mysql -u <user> -h <host> -p
|
||||
```
|
||||
|
||||
```sql
|
||||
CREATE DATABASE control_de_stock;
|
||||
USE control_de_stock;
|
||||
|
||||
CREATE TABLE producto(
|
||||
id INT AUTO_INCREMENT,
|
||||
nombre VARCHAR(50) NOT NULL,
|
||||
descripcion VARCHAR(255),
|
||||
cantidad INT NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY(id)
|
||||
)Engine=InnoDB;
|
||||
|
||||
INSERT INTO producto(
|
||||
nombre, descripcion, cantidad)
|
||||
values('Mesa', 'Mesa de 4 lugares', 10);
|
||||
|
||||
INSERT INTO producto(
|
||||
nombre, descripcion, cantidad)
|
||||
values( 'Celular', 'Celular Samsung', 50);
|
||||
|
||||
SELECT * FROM producto;
|
||||
|
||||
+----+----------+-------------------+----------+
|
||||
| id | nombre | descripcion | cantidad |
|
||||
+----+----------+-------------------+----------+
|
||||
| 1 | Mesa | Mesa de 4 lugares | 10 |
|
||||
| 2 | Celuclar | Celular Samsung | 50 |
|
||||
+----+----------+-------------------+----------+
|
||||
```
|
||||
|
||||
<br/>
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
||||
flowchart
|
||||
subgraph "Conexión a base de datos"
|
||||
DB1[(MySQL)]
|
||||
DB2[(SQL Server)]
|
||||
DB3[(MariaDB)]
|
||||
app1["Aplicación
|
||||
Java"]
|
||||
DV1[/"Driver MySQL
|
||||
MySqlConnector.getConnection()"\]
|
||||
DV2[/"Driver SQL Server
|
||||
SqlServerConnection.Provider.connect()"\]
|
||||
DV3[/MariaDB Driver\]
|
||||
DBC{{"JDBC
|
||||
DriverManager.getConnection()"}}
|
||||
app1-->DBC
|
||||
DBC-->DV1-->DB1
|
||||
DV1-->DB3
|
||||
DBC-->DV3-->DB3
|
||||
DBC-->DV2-->DB2
|
||||
end
|
||||
```
|
||||
|
||||
### Url de conexión
|
||||
|
||||
**`jdbc:<tipo_db>://<host:puerto>/<nombre_db>?<opc_params>`**
|
||||
|
||||
ejm. `jdbc:mysql//localhost:3306/control_de_stock`
|
||||
|
||||
## Proyecto
|
||||
|
||||
### Configuración de maven - [pom.xml](./java_jdbc/control-de-stock/pom.xml)
|
||||
|
||||
```xml
|
||||
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.alura</groupId>
|
||||
<artifactId>control-de-stock</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>Control de Stock</name>
|
||||
<description>Proyecto para trabajar con bases de datos con JDBC</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>8.0.33</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.plugins</groupId>
|
||||
<artifactId>maven.compiler.plugin</artifactId>
|
||||
<version>4.0.0</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<optimize>true</optimize>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
```
|
||||
|
||||
### Prueba del conector
|
||||
|
||||
```java
|
||||
package com.alura.tests;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class PruebaConexion {
|
||||
|
||||
private static String dbname = "control_de_stock";
|
||||
private static String dbuser = "alura";
|
||||
private static String dbpass = "alura";
|
||||
private static String dburl = "192.168.0.8:3306";
|
||||
private static String params = "useTimeZone=true&serverTimeZone=UTC";
|
||||
|
||||
public static void main(String[] args) throws SQLException {
|
||||
System.out.println("hola");
|
||||
Connection con = DriverManager.getConnection(
|
||||
"jdbc:mysql://"+dburl+"/"+dbname+"?"+params, dbuser, dbpass);
|
||||
con.close();
|
||||
System.out.println("chao");
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### Uso de Clase
|
||||
[ConnectionFactory](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/factory/ConnectionFactory.java)
|
||||
|
||||
```java
|
||||
package com.alura.jdbc.factory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class ConnectionFactory {
|
||||
|
||||
private static String dbdriver = "jdbc:mysql://";
|
||||
private static String dburl = dbdriver+"192.168.0.8:3306/";
|
||||
private static String params = "?useTimeZone=true&serverTimeZone=UTC";
|
||||
private static String dbname = "control_de_stock";
|
||||
private static String dbuser = "alura";
|
||||
private static String dbpass = "alura";
|
||||
|
||||
public Connection recuperaConexion() throws SQLException {
|
||||
return DriverManager.getConnection(dburl + dbname + params, dbuser, dbpass);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Uso de try with resources para las conexiones
|
||||
|
||||
En clase
|
||||
[ProductoController](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/controller/ProductoController.java)
|
||||
para cierre automático de recursos `Statement`, `ResultSet`, `Connection`.
|
||||
|
||||
Y tratamiento de *querys* con `PreparedStatement`
|
||||
|
||||
```java
|
||||
...
|
||||
|
||||
public void guardar(Map<String,String> producto) throws SQLException {
|
||||
String nombre = producto.get("NOMBRE");
|
||||
String descripcion = producto.get("DESCRIPCION");
|
||||
int cantidad = Integer.valueOf(producto.get("CANTIDAD"));
|
||||
int max_cantidad = 50;
|
||||
|
||||
final Connection con = new ConnectionFactory().recuperaConexion();
|
||||
try (con) {
|
||||
con.setAutoCommit(false);
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"INSERT INTO producto(nombre, descripcion, cantidad) VALUES(?,?,?)",
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
|
||||
try (statement) {
|
||||
do {
|
||||
int cantidad_a_guardar = Math.min(cantidad, max_cantidad);
|
||||
ejecutaRegistro(nombre, descripcion, cantidad_a_guardar, statement);
|
||||
cantidad -= max_cantidad;
|
||||
} while (cantidad > 0);
|
||||
con.commit();
|
||||
} catch (Exception e) {
|
||||
con.rollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
## Pool de conexiones
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
||||
flowchart
|
||||
subgraph "Conexión a base de datos"
|
||||
DB1[(MySQL)]
|
||||
DB2[(SQL Server)]
|
||||
DB3[(MariaDB)]
|
||||
app1("Aplicación
|
||||
Java")
|
||||
app2>"Connection
|
||||
Factory"]
|
||||
app1-->app2
|
||||
subgraph DS[Datasource]
|
||||
subgraph C3P0
|
||||
pl("Pool de
|
||||
Conexiones")
|
||||
end
|
||||
end
|
||||
app2-->DS-->DBC
|
||||
DV1[/"Driver MySQL
|
||||
MySqlConnector.getConnection()"\]
|
||||
DV2[/"Driver SQL Server
|
||||
SqlServerConnection.Provider.connect()"\]
|
||||
DV3[/MariaDB Driver\]
|
||||
DBC{{"JDBC
|
||||
DriverManager.getConnection()"}}
|
||||
DBC-->DV1-->DB1
|
||||
DV1-->DB3
|
||||
DBC-->DV3-->DB3
|
||||
DBC-->DV2-->DB2
|
||||
end
|
||||
```
|
||||
|
||||
### Implentando Pool Datasource en [ConnectionFactory](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/factory/ConnectionFactory.java)
|
||||
|
||||
|
||||
- [c3p0](https://www.mchange.com/projects/c3p0/) - DJBC3 Connection and Statement
|
||||
Pooling
|
||||
|
||||
- [mchange-commons-java](https://www.mchange.com/projects/mchange-commons-java/index.html)
|
||||
|
||||
Dependencias [pom.xml](./java_jdbc/control-de-stock/pom.xml)
|
||||
|
||||
```xml
|
||||
...
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>c3p0</artifactId>
|
||||
<version>0.9.5.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mchange</groupId>
|
||||
<artifactId>mchange-commons-java</artifactId>
|
||||
<version>0.2.20</version>
|
||||
</dependency
|
||||
...
|
||||
```
|
||||
|
||||
```java
|
||||
package com.alura.jdbc.factory;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import javax.sql.DataSource;
|
||||
import com.mchange.v2.c3p0.ComboPooledDataSource;
|
||||
|
||||
public class ConnectionFactory {
|
||||
|
||||
private final static String driver = "jdbc:mysql://";
|
||||
private final static String dbaddr = "192.168.0.8:3306/";
|
||||
private final static String params = "?useTimeZone=true&serverTimeZone=UTC";
|
||||
private final static String dbname = "control_de_stock";
|
||||
private final static String dburl = driver+dbaddr+dbname+params;
|
||||
private final static String dbuser = "alura";
|
||||
private final static String dbpass = "alura";
|
||||
|
||||
private DataSource datasource;
|
||||
|
||||
public ConnectionFactory() {
|
||||
var pooledDataSource = new ComboPooledDataSource();
|
||||
pooledDataSource.setJdbcUrl(dburl);
|
||||
pooledDataSource.setUser(dbuser);
|
||||
pooledDataSource.setPassword(dbpass);
|
||||
pooledDataSource.setMaxPoolSize(10);
|
||||
this.datasource = pooledDataSource;
|
||||
}
|
||||
|
||||
public Connection recuperaConexion() throws SQLException {
|
||||
return this.datasource.getConnection();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```txt
|
||||
Aug 14, 2023 11:33:59 PM com.mchange.v2.log.MLog
|
||||
INFO: MLog clients using java 1.4+ standard logging.
|
||||
Aug 14, 2023 11:34:00 PM com.mchange.v2.c3p0.C3P0Registry
|
||||
INFO: Initializing c3p0-0.9.5.5 [built 11-December-2019 22:18:33 -0800; debug? true; trace: 10]
|
||||
Aug 14, 2023 11:34:00 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource
|
||||
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> z8kfsxax1wlsb2gfqn07n|10dba097, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> z8kfsxax1wlsb2gfqn07n|10dba097, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://192.168.0.8:3306/control_de_stock?useTimeZone=true&serverTimeZone=UTC, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 10, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {password=******, user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
|
||||
Abriendo conexión nro: 1
|
||||
Abriendo conexión nro: 2
|
||||
Abriendo conexión nro: 3
|
||||
Abriendo conexión nro: 4
|
||||
Abriendo conexión nro: 5
|
||||
Abriendo conexión nro: 6
|
||||
Abriendo conexión nro: 7
|
||||
Abriendo conexión nro: 8
|
||||
Abriendo conexión nro: 9
|
||||
Abriendo conexión nro: 10
|
||||
```
|
||||
|
||||
```sql
|
||||
SHOW PROCESSLIST;
|
||||
|
||||
+-----+-------+--------------------+------------------+---------+------+----------+------------------+----------+
|
||||
| Id | User | Host | db | Command | Time | State | Info | Progress |
|
||||
+-----+-------+--------------------+------------------+---------+------+----------+------------------+----------+
|
||||
| 193 | alura | 192.168.0.10:36856 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 194 | alura | 192.168.0.10:36854 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 195 | alura | 192.168.0.10:36852 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 196 | alura | 192.168.0.10:36882 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 197 | alura | 192.168.0.10:36896 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 198 | alura | 192.168.0.10:36880 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 199 | alura | 192.168.0.10:36902 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 200 | alura | 192.168.0.10:36918 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 201 | alura | 192.168.0.10:36920 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 202 | alura | 192.168.0.10:36934 | control_de_stock | Sleep | 15 | | NULL | 0.000 |
|
||||
| 203 | alura | 192.168.0.8:42234 | NULL | Query | 0 | starting | show processlist | 0.000 |
|
||||
+-----+-------+--------------------+------------------+---------+------+----------+------------------+----------+
|
||||
11 rows in set (0.001 sec)
|
||||
```
|
||||
|
||||
## Dao
|
||||
|
||||
Data Access Object [wiki](https://en.wikipedia.org/wiki/Data_access_object) en
|
||||
clase
|
||||
[ProductoDAO](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/dao/ProductoDAO.java)
|
||||
|
||||
|
||||
```mermaid
|
||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
||||
flowchart
|
||||
subgraph "Conexión a base de datos"
|
||||
DB1[(MySQL)]
|
||||
DB2[(SQL Server)]
|
||||
DB3[(MariaDB)]
|
||||
app1("Aplicación
|
||||
Java")
|
||||
CF("Connection
|
||||
Factory")
|
||||
subgraph DAO
|
||||
direction RL
|
||||
MD[Modelo]
|
||||
CT[Controlador]
|
||||
CT-->CF
|
||||
CT-->MD
|
||||
end
|
||||
app1-->CT
|
||||
app1-->MD
|
||||
subgraph DS[Datasource]
|
||||
subgraph C3P0
|
||||
PC("Pool de
|
||||
Conexiones")
|
||||
end
|
||||
end
|
||||
CF-->DS-->DBC
|
||||
DV1[/"Driver MySQL
|
||||
MySqlConnector.getConnection()"\]
|
||||
DV2[/"Driver SQL Server
|
||||
SqlServerConnection.Provider.connect()"\]
|
||||
DV3[/MariaDB Driver\]
|
||||
DBC{{"JDBC
|
||||
DriverManager.getConnection()"}}
|
||||
DBC-->DV1-->DB1
|
||||
DV1-->DB3
|
||||
DBC-->DV3-->DB3
|
||||
DBC-->DV2-->DB2
|
||||
end
|
||||
```
|
||||
|
||||
```java
|
||||
package com.alura.jdbc.dao;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class ProductoDAO {
|
||||
private final Connection con;
|
||||
|
||||
public ProductoDAO(Connection conexion) {
|
||||
this.con = conexion;
|
||||
}
|
||||
|
||||
public void guardar(Producto producto) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"INSERT INTO producto(nombre, descripcion, cantidad) VALUES(?,?,?)",
|
||||
Statement.RETURN_GENERATED_KEYS);
|
||||
try (statement) {
|
||||
ejecutaRegistro(producto, statement);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void ejecutaRegistro(Producto producto, PreparedStatement statement)
|
||||
throws SQLException {
|
||||
statement.setString(1, producto.getNombre());
|
||||
statement.setString(2, producto.getDescripcion());
|
||||
statement.setInt(3, producto.getCantidad());
|
||||
statement.execute();
|
||||
final ResultSet resultSet = statement.getGeneratedKeys();
|
||||
try (resultSet) {
|
||||
while (resultSet.next()) {
|
||||
producto.setId(resultSet.getInt(1));
|
||||
System.out.println(String.format("Producto insertado %s: ", producto));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<Producto> listar() {
|
||||
List<Producto> resultado = new ArrayList<>();
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(
|
||||
"SELECT ID, NOMBRE, DESCRIPCION, CANTIDAD FROM producto;");
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
ResultSet resultSet = statement.getResultSet();
|
||||
while (resultSet.next()) {
|
||||
Producto fila = new Producto(
|
||||
resultSet.getInt("ID"),
|
||||
resultSet.getString("NOMBRE"),
|
||||
resultSet.getString("DESCRIPCION"),
|
||||
resultSet.getInt("CANTIDAD")
|
||||
);
|
||||
resultado.add(fila);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int modificar(Producto producto) {
|
||||
try {
|
||||
final String query = "UPDATE producto SET NOMBRE=?, DESCRIPCION=?, CANTIDAD=? WHERE ID=?;";
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.setString(1, producto.getNombre());
|
||||
statement.setString(2, producto.getDescripcion());
|
||||
statement.setInt(3, producto.getCantidad());
|
||||
statement.setInt(4, producto.getId());
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public int eliminar(Integer id) {
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement("DELETE FROM producto WHERE ID=?;");
|
||||
try (statement) {
|
||||
statement.setInt(1, id);
|
||||
statement.execute();
|
||||
int resultado = statement.getUpdateCount();
|
||||
return resultado;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
### MVC
|
||||
|
||||
El proyecto sigue el patrón **M**odelo **V**ista **Controlador**
|
||||
|
||||
Ejm. Producto
|
||||
|
||||
- [Modelo](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/modelo/Producto.java)
|
||||
- [Vista](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/view/ControlDeStockFrame.java)
|
||||
- [Controlador](./java_jdbc/control-de-stock/src/main/java/com/alura/jdbc/controller/ProductoController.java)
|
||||
|
||||
```java
|
||||
package com.alura.jdbc.controller;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alura.jdbc.dao.ProductoDAO;
|
||||
import com.alura.jdbc.factory.ConnectionFactory;
|
||||
import com.alura.jdbc.modelo.Producto;
|
||||
|
||||
public class ProductoController {
|
||||
|
||||
private ProductoDAO productoDAO;
|
||||
|
||||
public ProductoController() {
|
||||
this.productoDAO = new ProductoDAO(new ConnectionFactory().recuperaConexion());
|
||||
}
|
||||
|
||||
public int modificar(Producto producto) {
|
||||
return productoDAO.modificar(producto);
|
||||
}
|
||||
|
||||
public int eliminar(Integer id) {
|
||||
return productoDAO.eliminar(id);
|
||||
}
|
||||
|
||||
public List<Producto> listar() {
|
||||
return productoDAO.listar();
|
||||
}
|
||||
|
||||
public void guardar(Producto producto) {
|
||||
productoDAO.guardar(producto);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
- Para cada tabla del modelo hay una clase de dominio
|
||||
- Para la tabla de `producto` hay una clase `Producto` asociada
|
||||
- Los objetos del tipo `Producto` representan un registro de la tabla
|
||||
- Para acceder a la tabla se utiliza el estándar **Data Access Object (DAO)**
|
||||
- Para cada clase de dominio hay un **DAO** asociado. Ejm, la clase
|
||||
`Producto` posee la clase `ProductoDAO`
|
||||
- Todos los métodos JDBC relacionados al producto están encapsulados en `ProductoDAO`
|
||||
- Aplicación escrita en capas
|
||||
- Las capas más conocidas son las de **view**, **controller**, **modelo** y
|
||||
**persistencia**, que componen el estándar **MVC**
|
||||
- El flujo de una consulta entre las capas es el siguiente
|
||||
- `view` <--> `controller` <--> `persistencia`
|
||||
|
||||
> **Note** No es buena práctica dejar los detalles de implementación de una capa en otras
|
||||
que no tienen esta responsabilidad (ejm. la capa de controller lanzar una
|
||||
SQLException)
|
||||
>
|
||||
> Esta es una aplicación desktop embebida, pero hay otros tipos de aplicaciones
|
||||
con otros tipos de view, como html para aplicaciones web.
|
||||
|
||||
## Relación entre tablas
|
||||
|
||||
Creación tabla `categoria` + 4 categorías
|
||||
|
||||
```sql
|
||||
CREATE TABLE categoria(id INT AUTO_INCREMENT,
|
||||
nombre VARCHAR(50) NOT NULL,
|
||||
PRIMARY KEY(id)
|
||||
)Engine=InnoDB;
|
||||
|
||||
INSERT INTO categoria(nombre)
|
||||
VALUES('Muebles'),('Tecnología'),('Menaje'),('Calzado');
|
||||
```
|
||||
|
||||
Modifcando tabla para agregar la columna `categoria_id`
|
||||
|
||||
```sql
|
||||
ALTER TABLE producto ADD COLUMN categoria_id INT;
|
||||
```
|
||||
|
||||
Creando **llave foranea**
|
||||
|
||||
```sql
|
||||
ALTER TABLE producto ADD FOREIGN KEY(categoria_id) REFERENCES categoria(id);
|
||||
```
|
||||
|
||||
Asignación de categoría a productos
|
||||
|
||||
```sql
|
||||
UPDATE producto SET categoria_id=1 WHERE id=1;
|
||||
...
|
||||
UPDATE producto SET categoria_id=1 WHERE id>11 AND id<17;
|
||||
...
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT * FROM categoria;
|
||||
|
||||
+----+-------------+
|
||||
| id | nombre |
|
||||
+----+-------------+
|
||||
| 1 | Muebles |
|
||||
| 2 | Tecnología |
|
||||
| 3 | Menaje |
|
||||
| 4 | Calzado |
|
||||
+----+-------------+
|
||||
```
|
||||
|
||||
```sql
|
||||
SELECT * FROM producto;
|
||||
|
||||
+----+------------+--------------------------------+----------+--------------+
|
||||
| id | nombre | descripcion | cantidad | categoria_id |
|
||||
+----+------------+--------------------------------+----------+--------------+
|
||||
| 1 | Mesa | Mesa de 4 lugares | 10 | 1 |
|
||||
| 2 | Celular | Celular Samsung | 50 | 2 |
|
||||
| 3 | Vaso | Vaso de cristal | 10 | 3 |
|
||||
| 5 | Cuchara | Cuchara de plastico | 100 | 3 |
|
||||
| 7 | Mouse | Mouse inálambrico | 100 | 2 |
|
||||
| 9 | Linterna | Linterna con pilas recargables | 50 | 2 |
|
||||
| 11 | Zapatillas | Zapatillas de futbol | 40 | 4 |
|
||||
| 12 | Botellas | Botellas de vidrio | 50 | 1 |
|
||||
| 13 | Botellas | Botellas de plástico | 24 | 1 |
|
||||
| 14 | Platos | Platos de plastico | 50 | 1 |
|
||||
| 15 | Platos | Platos de plastico | 10 | 1 |
|
||||
| 16 | Platos | Platos de loza | 50 | 1 |
|
||||
| 30 | Teclado | Teclado inalámbrico | 6 | 2 |
|
||||
+----+------------+--------------------------------+----------+--------------+
|
||||
```
|
||||
|
||||
## Inner JOIN
|
||||
|
||||
Cuando se tiene una relación entre tablas se debe cuidar de no crear el problema
|
||||
de quieries `N+1`. Es decir, no buscar los datos de una relación en otras queries.
|
||||
|
||||
Esto puede producir problemas de performance tanto en la aplicación como en la DB.
|
||||
|
||||
Para ello utilizar ***join*** en la query SQL
|
||||
|
||||
```java
|
||||
...
|
||||
public List<Categoria> listarConProductos() {
|
||||
List<Categoria> resultado = new ArrayList<>();
|
||||
final String query = "SELECT C.ID, C.NOMBRE, P.ID, P.NOMBRE, P.CANTIDAD"
|
||||
+ "FROM categoria C INNER JOIN producto P ON C.ID = P.CATEGORIA_ID ";
|
||||
System.out.println(query);
|
||||
try {
|
||||
final PreparedStatement statement = con.prepareStatement(query);
|
||||
try (statement) {
|
||||
statement.execute();
|
||||
final ResultSet resultSet = statement.getResultSet();
|
||||
try (resultSet){
|
||||
while (resultSet.next()) {
|
||||
Integer categoriaId = resultSet.getInt("C.ID");
|
||||
String categoriaNombre = resultSet.getString("C.NOMBRE");
|
||||
var categoria = resultado
|
||||
.stream()
|
||||
.filter(cat -> cat.getId().equals(categoriaId))
|
||||
.findAny().orElseGet(() -> {
|
||||
Categoria cat = new Categoria(categoriaId,
|
||||
categoriaNombre);
|
||||
resultado.add(cat);
|
||||
return cat;
|
||||
});
|
||||
Producto producto = new Producto(resultSet.getInt("P.ID"),
|
||||
resultSet.getString("P.NOMBRE"),
|
||||
resultSet.getInt("P.CANTIDAD"));
|
||||
categoria.agregar(producto);
|
||||
}
|
||||
};
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
...
|
||||
```
|
||||
|
||||
Aplicación [Control de Stock](./java_jdbc/control-de-stock/)
|
||||
|