Java JDBC: FIN + Emprendimiento
1
.gitignore
vendored
@ -13,3 +13,4 @@ bin/
|
|||||||
*.uml
|
*.uml
|
||||||
*.uxf
|
*.uxf
|
||||||
*.umlcd
|
*.umlcd
|
||||||
|
target/
|
||||||
|
@ -434,9 +434,9 @@ anteceden y preceden
|
|||||||
```mermaid
|
```mermaid
|
||||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}}}%%
|
||||||
graph LR
|
graph LR
|
||||||
c1(cc1)-->c2(cc2)-->c1
|
c1((cc1))-->c2((cc2))-->c1
|
||||||
c2-->c3(cc3)-->c2
|
c2-->c3((cc3))-->c2
|
||||||
c3-->c4(cc4)-->c3
|
c3-->c4((cc4))-->c3
|
||||||
```
|
```
|
||||||
|
|
||||||
```java
|
```java
|
||||||
@ -605,18 +605,20 @@ public class TestRepasoArray {
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneX'}}}%%
|
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneX'}}}%%
|
||||||
flowchart RL
|
flowchart LR
|
||||||
jln(java.lang.number)-->jld(java.lang.Double)--bytes-->8
|
jln(java.lang.number)-->jld(java.lang.Double)-->b8
|
||||||
jln-->jlf(java.lang.Float)--bytes-->4
|
jln-->jlf(java.lang.Float)-->b4((4 bytes))
|
||||||
jln-->jll(java.lang.Long)--bytes-->8
|
jln-->jll(java.lang.Long)-->b8((8 bytes))
|
||||||
jln-->jli(java.lang.Integer)--bytes-->4
|
jln-->jli(java.lang.Integer)-->b4
|
||||||
jln-->jls(java.lang.Short)--bytes-->2
|
jln-->jls(java.lang.Short)-->b2((2 bytes))
|
||||||
jln-->jlb(java.lang.Byte)--bytes-->1
|
jln-->jlb(java.lang.Byte)-->b1((1 byte))
|
||||||
jln-->jlc(java.lang.Character)--bytes-->2
|
jln-->jlc(java.lang.Character)-->b2
|
||||||
jln-->jlbol(java.lang.Boolean)--bytes-->docs(JVM docs)
|
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
|
click docs "https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-2.html#jvms-2.3.4" "Documentación Java" _blank
|
||||||
```
|
```
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
```java
|
```java
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Double numero_double = 33.0;
|
Double numero_double = 33.0;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
- [Curso](https://app.aluracursos.com/course/lean-startup-metodo-eficaz-idea-negocio-empresa),
|
- [Curso](https://app.aluracursos.com/course/lean-startup-metodo-eficaz-idea-negocio-empresa),
|
||||||
Resumen [Lean Startup](./lean_startup.md)
|
Resumen [Lean Startup](./lean_startup.md)
|
||||||
- [Curso](https://app.aluracursos.com/course/emprendimiento-idea-plan-negocios),
|
- [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),
|
- [Curso](https://app.aluracursos.com/course/pitch-entrevistas-presentaciones-impactantes),
|
||||||
Resumen [Pitch para entrevistas]()
|
Resumen [Pitch para entrevistas]()
|
||||||
- Artículo
|
- 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)
|
- [Curso](https://app.aluracursos.com/course/introduccion-sql-mysql-manipule-consulte-datos)
|
||||||
Java y [bases de datos](./base_de_datos.md)
|
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
|
```sql
|
||||||
-- show databases;
|
-- show databases;
|
||||||
use jugos;
|
USE jugos;
|
||||||
CREATE TABLE cliente(
|
CREATE TABLE cliente(
|
||||||
dni VARCHAR(20),
|
dni VARCHAR(20),
|
||||||
nombre VARCHAR(150),
|
nombre VARCHAR(150),
|
||||||
@ -317,7 +317,7 @@ CREATE TABLE cliente(
|
|||||||
#### Creación de tabla **`vendedor`**
|
#### Creación de tabla **`vendedor`**
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
use jugos;
|
USE jugos;
|
||||||
CREATE TABLE vendedor(
|
CREATE TABLE vendedor(
|
||||||
matricula VARCHAR(4),
|
matricula VARCHAR(4),
|
||||||
nombre VARCHAR(100),
|
nombre VARCHAR(100),
|
||||||
@ -328,7 +328,7 @@ CREATE TABLE vendedor(
|
|||||||
#### Elimnar tabla
|
#### Elimnar tabla
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
use jugos;
|
USE jugos;
|
||||||
-- CREATE TABLE vendedor2(
|
-- CREATE TABLE vendedor2(
|
||||||
-- matricula VARCHAR(4),
|
-- matricula VARCHAR(4),
|
||||||
-- nombre VARCHAR(100),
|
-- 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/)
|
||||||
|
|