Java JDBC: FIN + Emprendimiento

This commit is contained in:
devfzn 2023-08-15 20:48:02 -04:00
parent 27f8a8ed08
commit 28791262a7
Signed by: devfzn
GPG Key ID: E070ECF4A754FDB1
35 changed files with 2111 additions and 17 deletions

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ bin/
*.uml *.uml
*.uxf *.uxf
*.umlcd *.umlcd
target/

View File

@ -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;

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View 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

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -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)

View File

@ -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),

View 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>

View File

@ -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);
}
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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();
}
}

View File

@ -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());
}
}

View File

@ -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));
}
}
}

View File

@ -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);
}
}

View File

@ -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() }
));
});
}
}

View File

@ -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
View 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/)