En esta segunda parte procederemos a crear las entidades de la aplicación, utilizando EclipseLink que implementa la especificación JPA que nos ayudará a manejar nuestra base de datos MySQL.
En este serie vamos a desarrollar una aplicación web usando Java EE, integrando las siguientes tecnologías EclipseLink (JPA 2.1), PrimeFaces 5.0 JSF 2.0.
Para ello usaremos NetBeans IDE 8.0.2, y de base de datos MySQL 5.6.25, usando MySQL JDBC Driver 5.1.23 para conectar nuestra aplicación Java con MySQL, y MySQL Workbench 6.3 para gestionar y visualizar la base de datos.
Contenido
Creación de clases
Las clases que procederemos a crear en nuestro proyecto son las que se muestran en el siguiente diagrama de clases:
En la pestaña de "Projects" expandimos nuestro proyectos, y damos click derecho en "Source Packages", elegimos New > Java Class del menú contextual.
En el cuadro de diálogo que aparece brindamos un nombre a nuestra clase en "Class Name", y en "Package" proporcionamos el nombre del paquete donde se guardarán las clases. Procedemos a crear la clase Genero, que estará dentro del paquete com.nes.entidades.
En nuestra nueva clase Genero, procedemos a codificar los atributos respectivos de la clase.
Elegimos cuales atributos deseamos generar los getters/setters (en este caso todos los atributos), y damos click en "Refactor".
Ahora nuestra clase Genero, tiene los métodos Get y Set respectivos para poder acceder a los atributos de la clase que están marcados como privados. El archivo Genero.java debe quedar de la siguiente manera:
Genero.java
Usuario.java
Creación de entidades
Para que nuestras clases de Java se vuelvan entidades de EclipseLink, se hace uso de la anotación @Entity. Esto indica a EclipseLink que la clase representa una tabla en nuestra base de datos. La anotación @Entity necesita que las clases que la utilicen implementen la interfaz Serializable del paquete java.io.Serializable. Por lo que también haremos que las clases implementen dicha interfaz.
También es necesario especificar cuál atributo de la clase será usado como llave primaria en la base de datos. Como todas nuestras clases tienen un atributo id de tipo entero usaremos ese atributo para que sea la llave primaria de las tablas en nuestra base de datos. Para eso, se usa la anotación @Id.
Además, para no preocuparnos por cómo generar la llave primaria con cada nuevo registro en nuestra aplicación, usaremos la anotación @GeneratedValue para indicar a EclipseLink que la llave primaria se generará automáticamente. También especificamos que la estrategia para generar las llaves primarias será mediante el uso del Identity en MySQL (también conocido como AUTO_INCREMENT), y esto lo hacemos con la propiedad GenerationType.IDENTITY dentro de la anotación @GeneratedValue.
En una base de datos, las tablas no se encuentran aisladas. Las tablas se encuentran asociadas con otras mediante llaves foráneas, y dependiendo de la cardinalidad, se tienen asociaciones uno a uno, uno a muchos, o muchos a muchos.
En nuestra aplicación, podemos observar que tenemos muchas asociaciones entre diferentes entidades, por citar algunas:
Haciendo uso de éstas anotaciones, nuestras clases quedan de la siguiente manera:
Genero.java
Si revisamos el código, podemos observar que la entidad DetallePedido, sí cuenta con una atributo llamado pedido, que es de tipo Pedido.
Agregando una unidad de persistencia
Si estuviste atento mientras implementabas las anotaciones en nuestras entidades, NetBeans muestra una advertencia: "The project doest not contain a persistence unit" o "El proyecto no contiene una unidad de persistencia".
Según la documentación de Oracle: "Una unidad de persistencia define un conjunto de entidades que son manejados por instancias de EntityManager en una aplicación. Este conjunto de entidades representan los datos contenidos en una única fuente de datos."
En este proyecto vamos a usar una única fuente de datos, la cual es nuestra base de datos MySQL, por lo cual es necesario crear una sola unidad de persistencia. Para crear la unidad de persistencias, en nuestro proyecto, damos click derecho, "New" > "Other".
Elegimos la carpeta "Persistence" en la sección de "Categories", y luego elegimos "Persistence Unit" de la sección "File Types", y damos click en Next.
Proveemos de un nombre a nuestra unidad de persistencia en "Persistence Unit Name" (en mi caso lo llamaré "WebAppPU"), elegimos como proveedor de persistencia ("Persistence Provider"), a EclipseLink, y en "Data Source", elegimos "New Data Source", nos aparecerá una ventana, y elegimos nuestra conexión a la base de datos creada anteriormente en la parte 1., y le proporcionamos un nombre (en mi caso lo llamaré "nes_java_db"). Toma nota del nombre de la unidad de persistencia que lo usaremos luego en esta parte.
Damos click en "Ok" para cerrar el cuadro de diálogo del Data Source, y en "Finish" para terminar de crear nuestra unidad de persistencia. NetBeans crea la unidad de persistencia en un archivo llamado "persistence.xml", bajo la carpeta "Configuration Files" en la pestaña de Projects. Damos doble click en persistence.xml para abrir el archivo.
Nos aseguramos que la opción "Use Java Transaction APIs" se encuentra deseleccionada, y que "Table Generation Strategy" se encuentre en "Create". La primera opción indica que no vamos a usar tecnología Java Transaction API (conocida como JTA), sino que nosotros mismos manejaremos las transacciones a nuestra base de datos. La segunda opción indica que las tablas se crearán en caso que no existan en la base de datos. (Si seguiste este tutorial paso a paso, recuerda que actualmente nuestra base de datos se encuentra vacía).
Nos aseguramos que la opción "Include All Entity Classes in "WebApp" Module" se encuentre deseccionada, y damos click en el botón "Add Class", elegimos todas nuestras entidades de la lista y damos click en "Ok" para agregarlas.
En el archivo persistence.xml hacemos click en el botón "Source" para visualizar el contenido del archivo, y debemos tener el contenido similar a este:
persistence.xml
persistence.xml
Probando las entidades
En esta parte crearemos un par de archivos de prueba, para probar que las entidades hayan sido programadas correctamente, y demostrar que nuestra aplicación realmente se conecta con la base de datos.
Damos click derecho a nuestro proyecto desde la pestaña de "Projects", y vamos a "New" > "Other".
En la sección de "Categories" elegimos la carpeta "Java", y en la sección de "File Types", elegimos la opción "Java Main Class", y damos click en "Next".
Damos un nombre a nuestro archivo y especificamos el paquete donde se guardará. En mi caso, lo llamaré "PruebaRegistro" dentro del paquete "com.nes.test", y damos click en "Finish" para crear nuestro archivo.
Para registrar la información de las entidades a la base de datos en JPA, se realiza a través del EntityManager (Gestor de entidades). Para ello, se tiene un EntityManagerFactory que se encarga de crear una instancia de EntityManager que podremos usar para registrar información a la base de datos. También como especificamos anteriormente que no usaremos Java Transaction API (JTA) para la gestión de las transacciones, lo haremos nosotros mismos en el código. Entonces, la secuencia de pasos que debe seguir el código para la prueba de registro queda de la siguiente manera:
PruebaRegistro.java
El archivo se ejecuta correctamente y se evidencia en la ventana de Output con el mensaje "BUILD SUCCESFUL"
Si revisamos nuestra base de datos, podemos observar que las tablas han sido creadas automáticamente, y que además han sido pobladas con los datos de nuestra prueba de registro.
De esta manera, nuestra base de datos queda como se muestra en el siguiente diagrama:
Cabe resaltar que en el código del archivo PruebaRegistro, en ninguna entidad usamos el método setId() para establecer el Id de nuestras entidades. Pero en la base de datos nos damos cuenta que el Id se ha creado automáticamente, esto es debido a la notación @GeneratedValue que pusimos en nuestras entidades, que hace que se generen de manera automática.
Conclusión - Link de Descarga del Proyecto
Recapitulando, en esta parte creamos las clases de entidades, encapsulamos sus atributos mediante los métodos getter y setter, y usamos las anotaciones de JPA para indicar que dichas clases son las que representaran a las tablas en la base de datos, y definimos las relaciones existentes entre ellas. Puedes descargar el código del proyecto de NetBeans hasta este punto haciendo click en este link.
En la siguiente parte, haremos una pequeña prueba de lectura de información en nuestra base de datos.
Referencias:
En este serie vamos a desarrollar una aplicación web usando Java EE, integrando las siguientes tecnologías EclipseLink (JPA 2.1), PrimeFaces 5.0 JSF 2.0.
Para ello usaremos NetBeans IDE 8.0.2, y de base de datos MySQL 5.6.25, usando MySQL JDBC Driver 5.1.23 para conectar nuestra aplicación Java con MySQL, y MySQL Workbench 6.3 para gestionar y visualizar la base de datos.
Contenido
- Creación de clases
- Creación de entidades
- Agregando una unidad de persistencia
- Probando las entidades
- Conclusión - Link de Descarga del Proyecto
Creación de clases
Las clases que procederemos a crear en nuestro proyecto son las que se muestran en el siguiente diagrama de clases:
En la pestaña de "Projects" expandimos nuestro proyectos, y damos click derecho en "Source Packages", elegimos New > Java Class del menú contextual.
En el cuadro de diálogo que aparece brindamos un nombre a nuestra clase en "Class Name", y en "Package" proporcionamos el nombre del paquete donde se guardarán las clases. Procedemos a crear la clase Genero, que estará dentro del paquete com.nes.entidades.
En nuestra nueva clase Genero, procedemos a codificar los atributos respectivos de la clase.
package com.nes.entidades;
public class Genero {
private int id;
private String nombre;
}
A continuación, procedemos a generar los getter y setters de la clase, para eso hacemos click derecho en cualquier lugar del código del archivo Género.java, elegimos "Refactor" > "Encapsulate fields" del menú.
Elegimos cuales atributos deseamos generar los getters/setters (en este caso todos los atributos), y damos click en "Refactor".
Ahora nuestra clase Genero, tiene los métodos Get y Set respectivos para poder acceder a los atributos de la clase que están marcados como privados. El archivo Genero.java debe quedar de la siguiente manera:
Genero.java
package com.nes.entidades;
public class Genero {
private int id;
private String nombre;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}
Repetimos la misma secuencia de pasos para crear las demás clases de la aplicación: Usuario, Libro, Tienda, DetallePedido, Pedido y Stock. Procederemos a codificar las clases y sus respectivos métodos getters y setters para cada atributo. Las clases resultantes deben quedar de esta manera:
Usuario.java
package com.nes.entidades;
import java.util.ArrayList;
import java.util.List;
public class Usuario {
private int id;
private String nombre;
private String usuario;
private String clave;
private boolean administrador;
private List pedidos = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getUsuario() {
return usuario;
}
public void setUsuario(String usuario) {
this.usuario = usuario;
}
public String getClave() {
return clave;
}
public void setClave(String clave) {
this.clave = clave;
}
public boolean isAdministrador() {
return administrador;
}
public void setAdministrador(boolean administrador) {
this.administrador = administrador;
}
public List getPedidos() {
return pedidos;
}
public void setPedidos(List pedidos) {
this.pedidos = pedidos;
}
}
Libro.java
package com.nes.entidades;
public class Libro {
private int id;
private String nombre;
private float precio;
private Genero genero;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public float getPrecio() {
return precio;
}
public void setPrecio(float precio) {
this.precio = precio;
}
public Genero getGenero() {
return genero;
}
public void setGenero(Genero genero) {
this.genero = genero;
}
}
Tienda.java
package com.nes.entidades;
public class Tienda {
private int id;
private String nombre;
private String direccion;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
}
DetallePedido.java
package com.nes.entidades;
public class DetallePedido {
private int id;
private Pedido pedido;
private Libro libro;
private float precioUnitario;
private int cantidad;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Pedido getPedido() {
return pedido;
}
public void setPedido(Pedido pedido) {
this.pedido = pedido;
}
public Libro getLibro() {
return libro;
}
public void setLibro(Libro libro) {
this.libro = libro;
}
public float getPrecioUnitario() {
return precioUnitario;
}
public void setPrecioUnitario(float precioUnitario) {
this.precioUnitario = precioUnitario;
}
public int getCantidad() {
return cantidad;
}
public void setCantidad(int cantidad) {
this.cantidad = cantidad;
}
}
Pedido.java
package com.nes.entidades;
import java.util.ArrayList;
import java.util.List;
public class Pedido {
private int id;
private Usuario usuario;
private Tienda tienda;
private List detalle = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public Tienda getTienda() {
return tienda;
}
public void setTienda(Tienda tienda) {
this.tienda = tienda;
}
public List getDetalle() {
return detalle;
}
public void setDetalle(List detalle) {
this.detalle = detalle;
}
}
Stock.java
package com.nes.entidades;
public class Stock {
private int id;
private Libro libro;
private Tienda tienda;
private int cantidad;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Libro getLibro() {
return libro;
}
public void setLibro(Libro libro) {
this.libro = libro;
}
public Tienda getTienda() {
return tienda;
}
public void setTienda(Tienda tienda) {
this.tienda = tienda;
}
public int getCantidad() {
return cantidad;
}
public void setCantidad(int cantidad) {
this.cantidad = cantidad;
}
}
Hasta este punto tenemos las clases que utilizaremos en nuestra aplicación. A continuación procederemos a convertir estas clases en Entidades de EclipseLink que representarán las tablas en nuestra base de datos.
Creación de entidades
Para que nuestras clases de Java se vuelvan entidades de EclipseLink, se hace uso de la anotación @Entity. Esto indica a EclipseLink que la clase representa una tabla en nuestra base de datos. La anotación @Entity necesita que las clases que la utilicen implementen la interfaz Serializable del paquete java.io.Serializable. Por lo que también haremos que las clases implementen dicha interfaz.
También es necesario especificar cuál atributo de la clase será usado como llave primaria en la base de datos. Como todas nuestras clases tienen un atributo id de tipo entero usaremos ese atributo para que sea la llave primaria de las tablas en nuestra base de datos. Para eso, se usa la anotación @Id.
Además, para no preocuparnos por cómo generar la llave primaria con cada nuevo registro en nuestra aplicación, usaremos la anotación @GeneratedValue para indicar a EclipseLink que la llave primaria se generará automáticamente. También especificamos que la estrategia para generar las llaves primarias será mediante el uso del Identity en MySQL (también conocido como AUTO_INCREMENT), y esto lo hacemos con la propiedad GenerationType.IDENTITY dentro de la anotación @GeneratedValue.
En una base de datos, las tablas no se encuentran aisladas. Las tablas se encuentran asociadas con otras mediante llaves foráneas, y dependiendo de la cardinalidad, se tienen asociaciones uno a uno, uno a muchos, o muchos a muchos.
En nuestra aplicación, podemos observar que tenemos muchas asociaciones entre diferentes entidades, por citar algunas:
- Un libro tiene un género y a su vez; un género puede estar presente en muchos libros. Esto es una relación de uno a muchos entre Libro y Genero
- Un usuario puede realizar muchos pedidos y a su vez; un pedido es realizado por un usuario. Esto es una relación de uno a muchos entre Usuario y Pedido
- Un usuario puede realizar muchos pedidos y a su vez; un pedido es realizado por un usuario. Esto es una relación de uno a muchos entre Usuario y Pedido
- Una tienda tiene una colección de existencias (stocks), y a su vez una existencia (stock) tiene está asignado a una tienda. Esto es una relación de uno a muchos entre Tienda y Stock.
Haciendo uso de éstas anotaciones, nuestras clases quedan de la siguiente manera:
Genero.java
package com.nes.entidades;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Genero implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nombre;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
}
Libro.java
package com.nes.entidades;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Libro implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nombre;
private float precio;
@ManyToOne
private Genero genero;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public float getPrecio() {
return precio;
}
public void setPrecio(float precio) {
this.precio = precio;
}
public Genero getGenero() {
return genero;
}
public void setGenero(Genero genero) {
this.genero = genero;
}
}
Stock.java
package com.nes.entidades;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Stock implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Libro libro;
@ManyToOne
private Tienda tienda;
private int cantidad;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Libro getLibro() {
return libro;
}
public void setLibro(Libro libro) {
this.libro = libro;
}
public Tienda getTienda() {
return tienda;
}
public void setTienda(Tienda tienda) {
this.tienda = tienda;
}
public int getCantidad() {
return cantidad;
}
public void setCantidad(int cantidad) {
this.cantidad = cantidad;
}
}
Tienda.java
package com.nes.entidades;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Tienda implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nombre;
private String direccion;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getDireccion() {
return direccion;
}
public void setDireccion(String direccion) {
this.direccion = direccion;
}
}
Usuario.java
package com.nes.entidades;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Usuario implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String nombre;
private String usuario;
private String clave;
private boolean administrador;
@OneToMany(mappedBy = "usuario")
private List pedidos = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getUsuario() {
return usuario;
}
public void setUsuario(String usuario) {
this.usuario = usuario;
}
public String getClave() {
return clave;
}
public void setClave(String clave) {
this.clave = clave;
}
public boolean isAdministrador() {
return administrador;
}
public void setAdministrador(boolean administrador) {
this.administrador = administrador;
}
public List getPedidos() {
return pedidos;
}
public void setPedidos(List pedidos) {
this.pedidos = pedidos;
}
}
Pedido.java
package com.nes.entidades;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
@Entity
public class Pedido implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Usuario usuario;
@ManyToOne
private Tienda tienda;
@OneToMany(mappedBy = "pedido")
private List detalle = new ArrayList<>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Usuario getUsuario() {
return usuario;
}
public void setUsuario(Usuario usuario) {
this.usuario = usuario;
}
public Tienda getTienda() {
return tienda;
}
public void setTienda(Tienda tienda) {
this.tienda = tienda;
}
public List getDetalle() {
return detalle;
}
public void setDetalle(List detalle) {
this.detalle = detalle;
}
}
DetallePedido.java
package com.nes.entidades;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class DetallePedido implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@ManyToOne
private Pedido pedido;
@ManyToOne
private Libro libro;
private float precioUnitario;
private int cantidad;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Pedido getPedido() {
return pedido;
}
public void setPedido(Pedido pedido) {
this.pedido = pedido;
}
public Libro getLibro() {
return libro;
}
public void setLibro(Libro libro) {
this.libro = libro;
}
public float getPrecioUnitario() {
return precioUnitario;
}
public void setPrecioUnitario(float precioUnitario) {
this.precioUnitario = precioUnitario;
}
public int getCantidad() {
return cantidad;
}
public void setCantidad(int cantidad) {
this.cantidad = cantidad;
}
}
Cabe resaltar que en la entidad Pedido usamos la anotación @OneToMany(mappedBy = "pedido") para especificar la relación de uno-a-muchos con la entidad DetallePedido. La propiedad mappedBy indica que la llave foránea se encuentra en el otro lado de la relación con el atributo proporcionado. En este caso particular, quiere decir en la entidad Pedido, se le indica que la llave foránea que la asocia con la entidad DetallePedido se encuentra dentro de la entidad DetallePedido en el atributo pedido. Este mismo escenario sucede entre la entidad Usuario y la entidad Pedido.
Si revisamos el código, podemos observar que la entidad DetallePedido, sí cuenta con una atributo llamado pedido, que es de tipo Pedido.
Agregando una unidad de persistencia
Si estuviste atento mientras implementabas las anotaciones en nuestras entidades, NetBeans muestra una advertencia: "The project doest not contain a persistence unit" o "El proyecto no contiene una unidad de persistencia".
Según la documentación de Oracle: "Una unidad de persistencia define un conjunto de entidades que son manejados por instancias de EntityManager en una aplicación. Este conjunto de entidades representan los datos contenidos en una única fuente de datos."
En este proyecto vamos a usar una única fuente de datos, la cual es nuestra base de datos MySQL, por lo cual es necesario crear una sola unidad de persistencia. Para crear la unidad de persistencias, en nuestro proyecto, damos click derecho, "New" > "Other".
Elegimos la carpeta "Persistence" en la sección de "Categories", y luego elegimos "Persistence Unit" de la sección "File Types", y damos click en Next.
Proveemos de un nombre a nuestra unidad de persistencia en "Persistence Unit Name" (en mi caso lo llamaré "WebAppPU"), elegimos como proveedor de persistencia ("Persistence Provider"), a EclipseLink, y en "Data Source", elegimos "New Data Source", nos aparecerá una ventana, y elegimos nuestra conexión a la base de datos creada anteriormente en la parte 1., y le proporcionamos un nombre (en mi caso lo llamaré "nes_java_db"). Toma nota del nombre de la unidad de persistencia que lo usaremos luego en esta parte.
Damos click en "Ok" para cerrar el cuadro de diálogo del Data Source, y en "Finish" para terminar de crear nuestra unidad de persistencia. NetBeans crea la unidad de persistencia en un archivo llamado "persistence.xml", bajo la carpeta "Configuration Files" en la pestaña de Projects. Damos doble click en persistence.xml para abrir el archivo.
Nos aseguramos que la opción "Use Java Transaction APIs" se encuentra deseleccionada, y que "Table Generation Strategy" se encuentre en "Create". La primera opción indica que no vamos a usar tecnología Java Transaction API (conocida como JTA), sino que nosotros mismos manejaremos las transacciones a nuestra base de datos. La segunda opción indica que las tablas se crearán en caso que no existan en la base de datos. (Si seguiste este tutorial paso a paso, recuerda que actualmente nuestra base de datos se encuentra vacía).
Nos aseguramos que la opción "Include All Entity Classes in "WebApp" Module" se encuentre deseccionada, y damos click en el botón "Add Class", elegimos todas nuestras entidades de la lista y damos click en "Ok" para agregarlas.
En el archivo persistence.xml hacemos click en el botón "Source" para visualizar el contenido del archivo, y debemos tener el contenido similar a este:
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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_1.xsd">
<persistence-unit name="WebAppPU" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>nes_java_db</non-jta-data-source>
<class>com.nes.entidades.DetallePedido</class>
<class>com.nes.entidades.Genero</class>
<class>com.nes.entidades.Libro</class>
<class>com.nes.entidades.Pedido</class>
<class>com.nes.entidades.Stock</class>
<class>com.nes.entidades.Tienda</class>
<class>com.nes.entidades.Usuario</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>
Procedemos a editar el archivo haciendo los siguientes cambios:
- Cambiamos la línea "<non-jta-data-source>nes_java_db</non-jta-data-source>" por "<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>"
- Bajo el nodo <properties> agregamos lo siguiente
- Agregamos la cadena de conexión:
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/nes_java_db?zeroDateTimeBehavior=convertToNull"/> - Agregamos el driver de MySQL:
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> - Agregamos el nombre de usuario de las credenciales de MySQL (en este caso, usaré el usuario root, tú puedes usar otro)
<property name="javax.persistence.jdbc.user" value="root"/> - Agregamos la clave del usuario de MySQL (mi clave es mysql, la tuya puede cambiar)
<property name="javax.persistence.jdbc.password" value="mysql"/>
persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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_1.xsd">
<persistence-unit name="WebAppPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>com.nes.entidades.DetallePedido</class>
<class>com.nes.entidades.Genero</class>
<class>com.nes.entidades.Libro</class>
<class>com.nes.entidades.Pedido</class>
<class>com.nes.entidades.Stock</class>
<class>com.nes.entidades.Tienda</class>
<class>com.nes.entidades.Usuario</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/nes_java_db?zeroDateTimeBehavior=convertToNull"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="mysql"/>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>
Con esto, ya tenemos nuestras entidades mapeadas, y nuestro proyecto configurado para que pueda conectarse con nuestra base de datos. En la siguiente parte, probaremos que las entidades se hayan programado correctamente.
Probando las entidades
En esta parte crearemos un par de archivos de prueba, para probar que las entidades hayan sido programadas correctamente, y demostrar que nuestra aplicación realmente se conecta con la base de datos.
Damos click derecho a nuestro proyecto desde la pestaña de "Projects", y vamos a "New" > "Other".
En la sección de "Categories" elegimos la carpeta "Java", y en la sección de "File Types", elegimos la opción "Java Main Class", y damos click en "Next".
Damos un nombre a nuestro archivo y especificamos el paquete donde se guardará. En mi caso, lo llamaré "PruebaRegistro" dentro del paquete "com.nes.test", y damos click en "Finish" para crear nuestro archivo.
Para registrar la información de las entidades a la base de datos en JPA, se realiza a través del EntityManager (Gestor de entidades). Para ello, se tiene un EntityManagerFactory que se encarga de crear una instancia de EntityManager que podremos usar para registrar información a la base de datos. También como especificamos anteriormente que no usaremos Java Transaction API (JTA) para la gestión de las transacciones, lo haremos nosotros mismos en el código. Entonces, la secuencia de pasos que debe seguir el código para la prueba de registro queda de la siguiente manera:
- Obtener una instancia del EntityManagerFactory
- Obtener una instancia de EntityManager usando la instancia del EntityManagerFactory
- Como vamos a registrar datos, es necesario abrir e iniciar una transacción en el EntityManager
- Instanciaremos nuestras entidades, y luego usaremos el método .persist() del EntityManager para registrarlas en la base de datos
- Finalizar la transacción haciendo un commit, para que se registre la información en la base de datos
- Cerrar el objeto EntityManager usando su método .close()
- Cerrar el objecto EntityManagerFactory usando su método .close()
PruebaRegistro.java
package com.nes.test;
import com.nes.entidades.DetallePedido;
import com.nes.entidades.Genero;
import com.nes.entidades.Libro;
import com.nes.entidades.Pedido;
import com.nes.entidades.Stock;
import com.nes.entidades.Tienda;
import com.nes.entidades.Usuario;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class PruebaRegistro {
public static void main(String[] args) {
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("WebAppPU");
EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin();
//Registrar un género
Genero genero = new Genero();
genero.setNombre("Drama");
entityManager.persist(genero);
//Registrar un Libro
Libro libro = new Libro();
libro.setNombre("Hamlet");
libro.setPrecio(22.99f);
libro.setGenero(genero);
entityManager.persist(libro);
//Registrar un Usuario
Usuario usuario = new Usuario();
usuario.setNombre("Fulano de Tal");
usuario.setUsuario("usuario");
usuario.setClave("1234");
usuario.setAdministrador(false);
entityManager.persist(usuario);
//Registrar una tienda
Tienda tienda = new Tienda();
tienda.setNombre("Tienda #1");
tienda.setDireccion("Av. Siempreviva 742");
entityManager.persist(tienda);
//Registrar Stock
Stock stock = new Stock();
stock.setLibro(libro);
stock.setTienda(tienda);
stock.setCantidad(12);
entityManager.persist(stock);
//Registrar un Pedido
Pedido pedido = new Pedido();
pedido.setTienda(tienda);
pedido.setUsuario(usuario);
entityManager.persist(pedido);
//Registrar DetallePedido
DetallePedido detallePedido = new DetallePedido();
detallePedido.setPedido(pedido);
detallePedido.setLibro(libro);
detallePedido.setPrecioUnitario(libro.getPrecio());
detallePedido.setCantidad(1);
entityManager.persist(detallePedido);
entityManager.getTransaction().commit();
entityManager.close();
entityManagerFactory.close();
}
}
Finalmente, ejecutamos el archivo PruebaRegistro dando doble click en cualquier lugar del código y seleccionando la opción "Run File", también podemos usar el atajo Shift+F6 desde el archivo para ejecutarlo.
El archivo se ejecuta correctamente y se evidencia en la ventana de Output con el mensaje "BUILD SUCCESFUL"
Si revisamos nuestra base de datos, podemos observar que las tablas han sido creadas automáticamente, y que además han sido pobladas con los datos de nuestra prueba de registro.
De esta manera, nuestra base de datos queda como se muestra en el siguiente diagrama:
Cabe resaltar que en el código del archivo PruebaRegistro, en ninguna entidad usamos el método setId() para establecer el Id de nuestras entidades. Pero en la base de datos nos damos cuenta que el Id se ha creado automáticamente, esto es debido a la notación @GeneratedValue que pusimos en nuestras entidades, que hace que se generen de manera automática.
Conclusión - Link de Descarga del Proyecto
Recapitulando, en esta parte creamos las clases de entidades, encapsulamos sus atributos mediante los métodos getter y setter, y usamos las anotaciones de JPA para indicar que dichas clases son las que representaran a las tablas en la base de datos, y definimos las relaciones existentes entre ellas. Puedes descargar el código del proyecto de NetBeans hasta este punto haciendo click en este link.
En la siguiente parte, haremos una pequeña prueba de lectura de información en nuestra base de datos.
Referencias:
No hay comentarios:
Publicar un comentario