JPA Hibernate: FIN

This commit is contained in:
devfzn 2023-09-05 02:07:58 -03:00
parent 28791262a7
commit b968bcdb07
Signed by: devfzn
GPG Key ID: E070ECF4A754FDB1
21 changed files with 808 additions and 117 deletions

View File

@ -7,3 +7,5 @@ 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)
- [Curso](https://app.aluracursos.com/course/persistencia-jpa-hibernate)
Persistencia con [JPA - Hibernate](./jpa_persistencia_hibernate.md)

View File

@ -11,13 +11,13 @@ public class CategoriaController {
private CategoriaDAO categoriaDAO;
public CategoriaController() {
var factory = new ConnectionFactory();
ConnectionFactory factory = new ConnectionFactory();
this.categoriaDAO = new CategoriaDAO(factory.recuperaConexion());
}
public List<Categoria> listar() {
return categoriaDAO.listar();
}
public List<Categoria> listar() {
return categoriaDAO.listar();
}
public List<Categoria> cargaReporte() {
return this.categoriaDAO.listarConProductos();

View File

@ -8,33 +8,33 @@ import com.alura.jdbc.modelo.Categoria;
import com.alura.jdbc.modelo.Producto;
public class ProductoController {
private ProductoDAO productoDAO;
public ProductoController() {
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 int eliminar(Integer id) {
return productoDAO.eliminar(id);
}
public List<Producto> listar() {
return productoDAO.listar();
}
public List<Producto> listar() {
return productoDAO.listar();
}
public List<Producto> listar(Categoria categoria) {
return productoDAO.listar(categoria.getId());
}
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

@ -18,7 +18,7 @@ public class CategoriaDAO {
}
public void guardar(Categoria categoria) {
try {
try {
final PreparedStatement statement = con.prepareStatement(
"INSERT INTO categoria(nombre) VALUES(?)",
Statement.RETURN_GENERATED_KEYS);
@ -33,22 +33,22 @@ public class CategoriaDAO {
private void ejecutaRegistro(Categoria categoria, PreparedStatement statement)
throws SQLException {
statement.setString(1, categoria.getNombre());
statement.execute();
final ResultSet resultSet = statement.getGeneratedKeys();
try (resultSet) {
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 {
try {
final PreparedStatement statement = con.prepareStatement(query);
try (statement) {
statement.execute();
@ -62,14 +62,14 @@ public class CategoriaDAO {
}
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int modificar(Categoria categoria) {
try {
final String query = "UPDATE categoria SET NOMBRE=? WHERE ID=?;";
try {
final String query = "UPDATE categoria SET NOMBRE=? WHERE ID=?;";
final PreparedStatement statement = con.prepareStatement(query);
try (statement) {
statement.setString(1, categoria.getNombre());
@ -78,13 +78,13 @@ public class CategoriaDAO {
int resultado = statement.getUpdateCount();
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int eliminar(Integer id) {
try {
try {
final PreparedStatement statement = con.prepareStatement("DELETE FROM categoria WHERE ID=?;");
try (statement) {
statement.setInt(1, id);
@ -92,9 +92,9 @@ public class CategoriaDAO {
int resultado = statement.getUpdateCount();
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public List<Categoria> listarConProductos() {
@ -102,7 +102,7 @@ public class CategoriaDAO {
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 {
try {
final PreparedStatement statement = con.prepareStatement(query);
try (statement) {
statement.execute();
@ -126,9 +126,9 @@ public class CategoriaDAO {
}
};
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return resultado;
}

View File

@ -17,7 +17,7 @@ public class ProductoDAO {
}
public void guardar(Producto producto) {
try {
try {
final PreparedStatement statement = con.prepareStatement(
"INSERT INTO producto(nombre, descripcion, cantidad, categoria_id) VALUES(?,?,?,?)",
Statement.RETURN_GENERATED_KEYS);
@ -32,22 +32,22 @@ public class ProductoDAO {
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) {
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 {
try {
final PreparedStatement statement = con.prepareStatement(
"SELECT ID, NOMBRE, DESCRIPCION, CANTIDAD, CATEGORIA_ID FROM producto;");
try (statement) {
@ -65,9 +65,9 @@ public class ProductoDAO {
}
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int modificar(Producto producto) {
@ -78,7 +78,7 @@ public class ProductoDAO {
query += " WHERE ID=?;";
}
try {
try {
final PreparedStatement statement = con.prepareStatement(query);
try (statement) {
statement.setString(1, producto.getNombre());
@ -95,13 +95,13 @@ public class ProductoDAO {
int resultado = statement.getUpdateCount();
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
public int eliminar(Integer id) {
try {
try {
final PreparedStatement statement = con.prepareStatement("DELETE FROM producto WHERE ID=?;");
try (statement) {
statement.setInt(1, id);
@ -109,16 +109,16 @@ public class ProductoDAO {
int resultado = statement.getUpdateCount();
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} 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 {
try {
final PreparedStatement statement = con.prepareStatement(query);
statement.setInt(1, id);
try (statement) {
@ -136,9 +136,9 @@ public class ProductoDAO {
}
return resultado;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -6,18 +6,18 @@ 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() {
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);
@ -25,13 +25,13 @@ public class ConnectionFactory {
pooledDataSource.setMaxPoolSize(10);
this.datasource = pooledDataSource;
}
public Connection recuperaConexion() {
//return DriverManager.getConnection(dburl, dbuser, dbpass);
try {
return this.datasource.getConnection();
public Connection recuperaConexion() {
//return DriverManager.getConnection(dburl, dbuser, dbpass);
try {
return this.datasource.getConnection();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}

View File

@ -6,11 +6,12 @@ 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();
}
public static void main(String[] args) throws SQLException {
System.out.println("Intentando conexión con Connetion Factory");
Connection con = new ConnectionFactory().recuperaConexion();
System.out.println("Prueba OK, cerrando conexión");
con.close();
}
}

View File

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

@ -223,7 +223,7 @@ public class ControlDeStockFrame extends JFrame {
Integer id = Integer.valueOf(modelo.getValueAt(tabla.getSelectedRow(), 0).toString());
int cantidadEliminada;
cantidadEliminada = this.productoController.eliminar(id);
cantidadEliminada = this.productoController.eliminar(id);
modelo.removeRow(tabla.getSelectedRow());
JOptionPane.showMessageDialog(this, cantidadEliminada+" Item eliminado con éxito!");
@ -231,17 +231,17 @@ public class ControlDeStockFrame extends JFrame {
}
private void cargarTabla() {
var productos = this.productoController.listar();
productos.forEach(producto -> modelo.addRow(
new Object[] {
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() {
@ -270,7 +270,7 @@ public class ControlDeStockFrame extends JFrame {
var categoria = (Categoria) comboCategoria.getSelectedItem();
this.productoController.guardar(producto, categoria.getId());
this.productoController.guardar(producto, categoria.getId());
JOptionPane.showMessageDialog(this, "Registrado con éxito!");
this.limpiarFormulario();
}

View File

@ -47,18 +47,18 @@ public class ReporteFrame extends JFrame {
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() }
));
});
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

@ -15,10 +15,10 @@ public class PruebaConexion {
private final static String dbpass = "alura";
public static void main(String[] args) throws SQLException {
System.out.println("hola");
System.out.println("Intentando conexión con DB");
Connection con = DriverManager.getConnection(dburl, dbuser, dbpass);
con.close();
System.out.println("chao");
System.out.println("Prueba OK, conexión cerrada");
}
}

View File

@ -0,0 +1,45 @@
<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.latam.alura.tienda</groupId>
<artifactId>tienda</artifactId>
<version>0.0.1-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<optimize>true</optimize>
<encoding>UTF-8</encoding>
<release>${java.version}</release>
<fork>true</fork>
<executable>/usr/bin/java</executable>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.6.15.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.222</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -0,0 +1,38 @@
package com.latam.alura.tienda.dao;
import java.util.List;
import javax.persistence.EntityManager;
import com.latam.alura.tienda.modelo.Categoria;
public class CategoriaDao {
private EntityManager em;
public CategoriaDao(EntityManager em) {
this.em = em;
}
public void guardar(Categoria categoria) {
this.em.persist(categoria);
}
public void actualizar(Categoria categoria) {
this.em.merge(categoria);
}
public void remover(Categoria categoria) {
categoria = this.em.merge(categoria);
this.em.remove(categoria);
}
public Categoria consultaPorId(Long id) {
return em.find(Categoria.class, id);
}
public List<Categoria> consultarTodos() {
String jpql = "SELECT P FROM Categoria AS P";
return em.createQuery(jpql, Categoria.class).getResultList();
}
}

View File

@ -0,0 +1,54 @@
package com.latam.alura.tienda.dao;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.EntityManager;
import com.latam.alura.tienda.modelo.Producto;
public class ProductoDao {
private EntityManager em;
public ProductoDao(EntityManager em) {
this.em = em;
}
public void guardar(Producto producto) {
this.em.persist(producto);
}
public void actualizar(Producto producto) {
this.em.merge(producto);
}
public void remover(Producto producto) {
producto = this.em.merge(producto);
this.em.remove(producto);
}
public Producto consultaPorId(Long id) {
return em.find(Producto.class, id);
}
public List<Producto> consultarTodos() {
String jpql = "SELECT P FROM Producto AS P";
return em.createQuery(jpql, Producto.class).getResultList();
}
public List<Producto> consultaPorNombre(String nombre) {
String jpql = "SELECT P FROM Producto AS P WHERE P.nombre=:nombre";
return em.createQuery(jpql, Producto.class).setParameter("nombre", nombre).getResultList();
}
public List<Producto> consultaPorNombreDeCategoria(String nombre) {
String jpql = "SELECT P FROM Producto AS P WHERE P.categoria.nombre=:nombre";
return em.createQuery(jpql, Producto.class).setParameter("nombre", nombre).getResultList();
}
public BigDecimal consultaPrecioPorNombreDeProducto(String nombre) {
String jpql = "SELECT P.precio FROM Producto AS P WHERE P.nombre=:nombre";
return em.createQuery(jpql, BigDecimal.class).setParameter("nombre", nombre).getSingleResult();
}
}

View File

@ -0,0 +1,46 @@
package com.latam.alura.tienda.modelo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
//public enum Categoria {
// SOFTWARES,
// LIBROS,
// CELULARES
//}
@Entity
@Table(name="categorias")
public class Categoria {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String nombre;
public Categoria() {}
public Categoria(String nombre) {
this.nombre = nombre;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}

View File

@ -0,0 +1,75 @@
package com.latam.alura.tienda.modelo;
import java.math.BigDecimal;
import java.time.LocalDate;
import javax.persistence.Entity;
//import javax.persistence.EnumType;
//import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name="productos")
public class Producto {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
// @Column(name="nombres")
private String nombre;
private String descripcion;
private BigDecimal precio;
private LocalDate fechaDeRegistro = LocalDate.now();
//@Enumerated(EnumType.STRING)
@ManyToOne
private Categoria categoria;
public Producto() {}
public Producto(String nombre, String descripcion, BigDecimal precio, Categoria categoria) {
this.nombre = nombre;
this.descripcion = descripcion;
this.precio = precio;
this.categoria = categoria;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDescripcion() {
return descripcion;
}
public void setDescripcion(String descripcion) {
this.descripcion = descripcion;
}
public BigDecimal getPrecio() {
return precio;
}
public void setPrecio(BigDecimal precio) {
this.precio = precio;
}
public LocalDate getFechaDeRegistro() {
return fechaDeRegistro;
}
}

View File

@ -0,0 +1,121 @@
package com.latam.alura.tienda.prueba;
import java.math.BigDecimal;
import java.util.List;
import javax.persistence.EntityManager;
//import javax.persistence.EntityManagerFactory;
//import javax.persistence.Persistence;
import com.latam.alura.tienda.dao.CategoriaDao;
import com.latam.alura.tienda.dao.ProductoDao;
import com.latam.alura.tienda.modelo.Categoria;
import com.latam.alura.tienda.modelo.Producto;
import com.latam.alura.tienda.utils.JPAUtils;
public class RegistroDeProducto {
public static void main(String[] args) {
RegistrarProducto();
EntityManager em = JPAUtils.getEntityManager();
ProductoDao productoDao = new ProductoDao(em);
Producto producto = productoDao.consultaPorId(1L);
System.out.println(producto.getNombre());
List<Producto> productos = productoDao.consultarTodos();
productos.forEach(producto_ -> System.out.println(producto_.getDescripcion()));
CategoriaDao categoriaDao = new CategoriaDao(em);
List<Categoria> categorias = categoriaDao.consultarTodos();
categorias.forEach(categoria_ -> System.out.println(categoria_.getNombre()));
List<Producto> productos_por_nombre = productoDao.consultaPorNombre("Samsung");
productos_por_nombre.forEach(producto_ -> System.out.println(producto_.getDescripcion()));
List<Producto> productos_por_nombre_categoria = productoDao.consultaPorNombreDeCategoria("Celulares");
productos_por_nombre_categoria.forEach(producto_ -> System.out.println(producto_.getDescripcion()));
BigDecimal precio_producto = productoDao.consultaPrecioPorNombreDeProducto("Samsung");
System.out.println(precio_producto);
/*
Categoria celulares = new Categoria("Celulares");
//Producto celular = new Producto("Samsung", "Teléfono usado", new BigDecimal("1000"), Categoria.CELULARES);
Producto celular = new Producto("Samsung", "Teléfono usado", new BigDecimal("1000"), celulares);
//celular.setNombre("Samsung");
//celular.setDescripcion("Teléfono usado");
//celular.setPrecio(new BigDecimal("1000"));
//EntityManagerFactory factory = Persistence.createEntityManagerFactory("tienda");
//EntityManager em = factory.createEntityManager();
EntityManager em = JPAUtils.getEntityManager();
ProductoDao productoDao = new ProductoDao(em);
CategoriaDao categoriaDao = new CategoriaDao(em);
em.getTransaction().begin();
categoriaDao.guardar(celulares);
productoDao.guardar(celular);
//em.persist(celular);
//em.getTransaction().commit();
em.flush();
em.clear();
//em.close();
*/
// Acciones por aula
//em.getTransaction().begin();
//V1
/*
em.getTransaction().begin();
em.persist(celulares);
celulares.setNombre("LAPTOPS");
em.getTransaction().commit();
em.close();
celulares.setNombre("PANTALLAS");
*/
//V2
/*
em.persist(celulares);
celulares.setNombre("LAPTOPS");
em.flush();
em.clear();
celulares = em.merge(celulares);
celulares.setNombre("PANTALLAS");
em.flush();
em.remove(celulares);
*/
//V3
/*
em.persist(celulares);
celulares.setNombre("LAPTOPS");
em.flush();
em.clear();
celulares = em.merge(celulares);
celulares.setNombre("PANTALLAS");
em.flush();
//em.clear();
em.remove(celulares);
em.flush();
*/
}
public static void RegistrarProducto() {
Categoria celulares = new Categoria("Celulares");
Producto celular = new Producto("Samsung", "Teléfono usado", new BigDecimal("1000"), celulares);
EntityManager em = JPAUtils.getEntityManager();
ProductoDao productoDao = new ProductoDao(em);
CategoriaDao categoriaDao = new CategoriaDao(em);
em.getTransaction().begin();
categoriaDao.guardar(celulares);
productoDao.guardar(celular);
em.getTransaction().commit();
em.close();
}
}

View File

@ -0,0 +1,14 @@
package com.latam.alura.tienda.utils;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class JPAUtils {
private static EntityManagerFactory FACTORY = Persistence.createEntityManagerFactory("tienda");
public static EntityManager getEntityManager() {
return FACTORY.createEntityManager();
}
}

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="tienda" transaction-type="RESOURCE_LOCAL">
<!-- En caso de utilizar otro framework distinto de Hibernate
se deben especificar las entidades
<class>com.latam.alura.tienda.modelo.Producto</class>
-->
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:tienda;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
<!-- hibernate.hdbm2ddl.auto values:
- create: Crea tabla, columnas y datos, de manera persistente
- create-drop: Igual que create, pero elimina todo al terminar la applicación.
- validate: Verifica que todo esté correcto
- update: Crea en caso de que no existan elementos, tablas o datos. Persistente
-->
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,264 @@
# JPA
<style>div.mermaid{text-align: center;}</style>
## Java Persistence API
[H2 Database Engine](https://mvnrepository.com/artifact/com.h2database/h2/2.2.222)
### JDBC
- Especificación para acceso al banco de datos relacional JAVA
- Abstracción del protocolo de comunicación con BD
- Drivers de la BD son implementaciones de JDBC
- Impacto mínimo en la aplicación al cambiar de BD
- Pattern DAO ayuda a aislar el código entre la API y el JDBC
```mermaid
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
flowchart
subgraph JDBC
DB[(Base de Datos)]
CS("Controller/Service
(Lógica de Negocios)")
style CS fill:#3f3f3f,stroke:#000,stroke-width:2px
DAO("DAO
(JDBC)")
style DAO fill:#3f3f3f,stroke:#000,stroke-width:2px
CS-->DAO-->DB
end
```
Ejemplo
```java
public class RegistroDeProductoService {
private ProductoDao dao;
public RegistroDeProductoService(ProductoDao dao) {
this.dao = dao;
}
public void registrarProducto(Producto producto) {
// lógica de negocio
this.dao.registrar(producto);
}
}
```
### Desventajas de JDBC
- Demasiado detalle, muchas lineas de código
- Alto acoplamiento con la BD, cualquier cambio en una parte tiene alto impacto
en otra parte
### Hibernate
- Creado en el año 2001 por ***Gavin King***
- Alternativa a JDBC/EJB 2
- Posteriormente Gavin King fue contratado por Red Hat
### JPA
- Especificación para ORM (Object Relational Mapping) en JAVA
- Lanzada el 2006
- Versión 2.0 lanzada el 2009
- Hibernate 3.5.0 (2010) paso a soportar JPA 2
```mermaid
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
flowchart
subgraph " "
direction BT
JP(JPA)
HB(Hibernate)
style HB fill:#3f3f3f,stroke:#000,stroke-width:2px
EL(EclipseLink)
style EL fill:#3f3f3f,stroke:#000,stroke-width:2px
OJP(OpenJPA)
style OJP fill:#3f3f3f,stroke:#000,stroke-width:2px
HB-->JP
EL-->JP
OJP-->JP
end
```
JPA es una capa (una abstarcción) se debe usar una biblioteca que la implemente
Existen detalles específicos de Hibernate que dificultan cambiar de implementacion
de JPA. Es recomendable mantenerse dentro del patrón de JPA.
EclipseLink es la implementación de referencia de JPA.
pom.xml
```xml
...
<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>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.6.15.Final</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>2.2.222</version>
<scope>test</scope>
</dependency>
</dependencies>
...
```
[/tienda/src/main/resources/META-INF/persistence.xml](./jpa/tienda/src/main/resources/META-INF/persistence.xml)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.2"
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd">
<persistence-unit name="tienda" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
<property name="javax.persistence.jdbc.url" value="jpdc:h2:mem:tienda"/>
<property name="javax.persistence.jdbc.user" value="sa"/>
<property name="javax.persistence.jdbc.password" value=""/>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
</properties>
</persistence-unit>
</persistence>
```
### Mapeo de entidades
```mermaid
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'monotoneY'}}}%%
flowchart
subgraph " "
DB[(Base de Datos)]
EN(Entidades)
style EN fill:#3f3f3f,stroke:#000,stroke-width:2px
subgraph ORM
OR("Tablas == Clases
Columnas == Atributos
Filas == Objetos")
style ORM fill:#3f3f3f,stroke:#000,stroke-width:2px
end
ORM-->EN-->DB
end
```
Entidades
```mermaid
erDiagram
Productos }|--|| Categorias : tiene
Productos {
id bigint PK
Nombre varchar
Descripcion varchar
Precio decimal
categoria_id int FK
}
Categorias {
id biging PK
nombre string
}
```
### Ciclo de vida de una entidad en JPA
```mermaid
%%{init: {'theme': 'dark','themeVariables': {'clusterBkg': '#2b2f38'}, 'flowchart': {'curve': 'linear'}}}%%
flowchart
subgraph " "
NO["operador
new"]
TR(tranciente)
NO-->TR
MG(Managed)
TR-->MG
subgraph " "
RM(removed)
DT(detached)
MG<-->RM
MG<--"close, clear
detach"-->DT
end
direction TB
DB[(Base de Datos)]
MG--"flush,
commit"-->DB
DB--"find,
query"-->MG
end
style DT fill:#3f3f3f,stroke:#000,stroke-width:2px
style RM fill:#3f3f3f,stroke:#000,stroke-width:2px
```
#### Estados de una Transacción
- Transiente
- Managed
**flush()**: permite realizar un rollback.
**commit()**: los cambios son definitivos.
**close()**: cierra el ***EntityManager***.
**clear()**: envia todas las entidades a un estado ***detach*** (ahorro de memoria).
**merge()**: actualiza un registro (primero realiza un select, luego se debe
asignar para su posterior merge, trae un registro al estado *Managed*).
**remove()**: delete registro si tiene estado *managed*.
- Detached
- Removed
### Consultas JPA
[ProductoDao.java](./jpa/tienda/src/main/java/com/latam/alura/tienda/dao/ProductoDao.java)
```java
...
public Producto consultaPorId(Long id) {
return em.find(Producto.class, id);
}
public List<Producto> consultarTodos() {
String jpql = "SELECT P FROM Producto AS P";
return em.createQuery(jpql, Producto.class).getResultList();
}
public List<Producto> consultaPorNombre(String nombre) {
String jpql = "SELECT P FROM Producto AS P WHERE P.nombre=:nombre";
return em.createQuery(jpql, Producto.class).setParameter("nombre", nombre).getResultList();
}
public List<Producto> consultaPorNombreDeCategoria(String nombre) {
String jpql = "SELECT P FROM Producto AS P WHERE P.categoria.nombre=:nombre";
return em.createQuery(jpql, Producto.class).setParameter("nombre", nombre).getResultList();
}
public BigDecimal consultaPrecioPorNombreDeProducto(String nombre) {
String jpql = "SELECT P.precio FROM Producto AS P WHERE P.nombre=:nombre";
return em.createQuery(jpql, BigDecimal.class).setParameter("nombre", nombre).getSingleResult();
}
}
```
----
Archivos de configuración:
- [pom.xml](./jpa/tienda/pom.xml)
- [presistence.xml](./jpa/tienda/src/main/resources/META-INF/persistence.xml)

View File

@ -47,3 +47,5 @@ primoridiales en programación con Javascript
- [Emprendimiento](./009_emprendimiento/)
- [Spring Boot](./010_spring_boot/README.md)
- [Base de datos](./010_spring_boot/base_de_datos.md)
- [JDBC](./010_spring_boot/jdbc.md)
- [Persistencia con JPA - Hibernate](./010_spring_boot/jpa_persistencia_hibernate.md)