En este post te explico como crear tu proyecto en JAVA implementando el patrón Singleton y el patrón Repository, haciendo uso de MySQL y JDBC para las consultas en nuestro proyecto.
En este post estaremos usando Netbeans, crearemos un nuevo proyecto:
Dentro de nuestro proyecto crearemos los siguientes packages:
Siguiendo el mismo patron:
"com.yourname.nameproject.carpeta.subcarpeta"
Para terminar de configurar el proyecto debemos descargar el conector MySQL para poder tener el Driver que nos permite conectarnos a nuestra base de datos y hacer consultas SQL.
Ya que creamos el proyecto con Maven, nos vamos a nuestro archivo pom.xml y agregamos la dependencia del conector MySQL, el cual lo encontramos en el siguiente enlace:
Maven Dependency MySQL Connector/J
Buscamos el siguiente apartado, y elegimos la version del conector:
Una vez dar clic, nos mandara al apartado donde encontraremos la dependencia del conector listo para copiar y pegar:
Y pegamos el codigo en el archivo pom.xml:
Para terminar, le daremos clic derecho a nuestro proyecto y seleccionamos clean and build, para descargar la dependencia y empezar con el poryecto:
Una vez creado nuestra estructura del proyecto empezaremos a seguir el paso a paso.
Singleton
Es un patrón de diseño creacional cuyo propósito principal es garantizar que una clase tenga una única instancia en toda la aplicación y proporcionar un punto de acceso global a ella.
Para empezar a implementar este patron, nos iremos al package com.yourname.nameproject.util y agregaremos una nueva clase llamada Conexion y agregaremos el siguiente código:
public class Conexion {
private static Conexion instance;
private Connection conn;
private String url = "jdbc:mysql://localhost:3306/nombredebasededato";
private String user = "tuusuario";
private String pass = "tuconstraseña";
// ------------------------------------------------------------------
}
Primero, agregamos un atributo estatico privado que guardara la instancia única, seguido de los atributos que nos serviran para conectarnos a nuestra base de datos.
public class Conexion {
private static Conexion instance;
private Connection conn;
private String url = "jdbc:mysql://localhost:3306/nombredebasededato";
private String user = "tuusuario";
private String pass = "tuconstraseña";
// ------------------------------------------------------------------
private Conexion () {
try {
conn = DriverManager.getConnection(url, user, pass);
if (conn != null) {
System.out.println("Conectado a la base de datos.");
}
} catch (SQLException e) {
System.out.println("Error al conectar la base de datos. " + e.getMessage());
}
}
}
Segundo, creamos el constructor privado para evitar instancias externas, dentro insertamos un bloque try catch para conectarnos a la base de datos y hacer la validacion correspondiente en caso de que la conexion sea exitosa o tenga un error.
public class Conexion {
private static Conexion instance;
private Connection conn;
private String url = "jdbc:mysql://localhost:3306/nombredebasededato";
private String user = "tuusuario";
private String pass = "tuconstraseña";
// ------------------------------------------------------------------
private Conexion () {
try {
conn = DriverManager.getConnection(url, user, pass);
if (conn != null) {
System.out.println("Conectado a la base de datos.");
}
} catch (SQLException e) {
System.out.println("Error al conectar la base de datos. " + e.getMessage());
}
}
// ------------------------------------------------------------------
public static synchronized Conexion getInstance () {
if (instance == null) {
instance = new Conexion();
}
return instance;
}
public Connection getConn() {
return conn;
}
}
Tercero, agregamos los siguientes metodos, un metodo publico estatico para obtener la instancia, y un metodo publico de tipo Connection que nos retorna la Conexion.
Hasta aca tenemos la clase Conexion que nos permitira conectarnos a la base de datos, en caso de correr nuestro programa y consultar los datos a la base de datos nos marcara un mensaje de confirmacion de que se conecto a la base de datos, caso contrario, nos indicara un mensaje de error.
Repository
Es un patrón de diseño que abstrae la capa de datos, actuando como una colección en memeoria que intermedia entre la lógica de negocio (dominio) y el almacenamiento fisico (base de datos, archivos, API's). Su objetivo principal es desacoplar el dominio de la tecnologia de persistencia, permitiendo cambiar el origen de datos sin alterar las reglas de negocio.
A diferencia del clasico patrón DAO (Data Access Object) que esta orientado directamente a tablas, el Repository esta oriendato al dominio y puede consolidar datos porvenientes de multiples fuentes en un solo objeto de negocio.
Para crear nuestro interfaz Repository nos iremos al package com.yourname.nameproject.repository y agregaremos un nuevo archivo de tipo Interface:
Y buscamos el siguiente apartado:
Le damos en "next" y lo guardamos como "Repository", nos creara nuestra Interface:
public interface Repository {
}
Para empezar con nuestra Interface le agregaremos un parámetro de tipo genérico, para ello pondremos el comodín <T> que significa que nuestra Interface sera genérica, esto nos permite que cuando implementemos nuestra Interface podamos definir el tipo exacto segun sea el contexto:
public interface Repository <T> {
}
Este comodín se coloca despues del nombre que le asignamos a nuestra Interface.
Ahora crearemos los metodos que vamos a implementar, siempre aplicando el comodín <T>, en este caso crearemos los siguientes métodos:
public interface Repository <T> {
List<T> findAll();
T getById(Integer id);
void save(T t);
void delete(Integer id);
}
El primer método List<T> findAll() nos devolverá una lista con el tipo de dato que definamos, puede ser una entidad en forma de objeto.
El segundo método T getById(Integer id) nos devolverá un objeto del tipo de dato que definamos, de igual forma puede ser una entidad en forma de objeto.
El tercer método void save(T t) hara la función de guardar un nuevo registro, el cual recibe como parámetro un tipo de dato que definamos, en este ejemplo, es una entidad de tipo objeto.
El cuarto método void delete(Integer id) hará la función de eliminar un registro, el cual recibe como parametro un id de tipo Integer.
Estos métodos deberán ser implementados según correspondan.
El objeto del negocio
Es la entidad del dominio, es decir, son las entidades de nuestra base de datos convertidas en objetos, te mostrare el ejemplo de dos entidades que se relacionan para que veas como es la logica en donde se implementan las operaciones SQL, veamos el siguiente ejemplo:
create table if not exists ecosistema(
id int not null auto_increment primary key,
nombreEcosistema varchar(100) not null,
creadoEn datetime default current_timestamp,
modificadoEn timestamp default current_timestamp on update current_timestamp
);
create table if not exists categoria(
id int not null auto_increment primary key,
categoria varchar(100) not null,
idEcosistema int not null,
creadoEn datetime default current_timestamp,
modificadoEn timestamp default current_timestamp on update current_timestamp,
foreign key (idEcosistema) references ecosistema(id) on delete cascade on update cascade
);
Acá tenemos dos tablas, una llamada ecosistema y otra llamada categoria, en esta se encuentra la llave foranea de ecosistema, crearemos los objetos de estas entidades.
Nos ubicamos en com.yourname.nameproject.model, crearemos dos clases llamadas Ecosistema, y otra llamada Categoria:
Le damos en "next" y las nombramos... nos creara las clases, y en estas mapearemos los campos de nuestra entidad.
Empezaremos con la clase Ecosistema:
public class Ecosistema {
private Integer id;
private String nombreEcosistema;
private LocalDateTime creadoEn;
private OffsetDateTime modificadoEn;
// constructor vacio
public Ecosistema() { }
// constructor para invocarlo al hacer la operacion INSERT
public Ecosistema(String nombreEcosistema) {
this.nombreEcosistema = nombreEcosistema;
}
// constructor para invocarlo al hacer la operacion UPDATE
public Ecosistema(String nombreEcosistema, Integer id) {
this.nombreEcosistema = nombreEcosistema;
this.id = id;
}
// getters and setters
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNombreEcosistema() {
return nombreEcosistema;
}
public void setNombreEcosistema(String nombreEcosistema) {
this.nombreEcosistema = nombreEcosistema;
}
public LocalDateTime getCreadoEn() {
return creadoEn;
}
public void setCreadoEn(LocalDateTime creadoEn) {
this.creadoEn = creadoEn;
}
public OffsetDateTime getModificadoEn() {
return modificadoEn;
}
public void setModificadoEn(OffsetDateTime modificadoEn) {
this.modificadoEn = modificadoEn;
}
// toString
@Override
public String toString() {
return this.nombreEcosistema;
}
}
En los atributos podemos observar los campos de la entidad, hay dos tipos de datos especiales, como LocalDateTime & OffsetDateTime, estos tipos son para el tipo de dato de nuestra base de datos que hemos definido como datetime & timestamp.
Seguido de un constructor vacío, y dos constructores mas, que nos serviran para hacer la operacion INSERT & UPDATE.
Tambien los métodos get() & set(), y un método toString().
Continuamos con la clase Categoria:
public class Categoria {
private Integer id;
private String categoria;
private Ecosistema ecosistema;
private LocalDateTime creadoEn;
private OffsetDateTime modificadoEn;
// constructor vacio
public Categoria() { }
// constructor para invocar al hacer la operacion INSERT
public Categoria(String categoria, Ecosistema ecosistema) {
this.categoria = categoria;
this.ecosistema = ecosistema;
}
// constructor para invocar al hacer la operacion UPDATE
public Categoria(String categoria, Ecosistema ecosistema, Integer id) {
this.categoria = categoria;
this.ecosistema = ecosistema;
this.id = id;
}
// getters and setters
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCategoria() {
return categoria;
}
public void setCategoria(String categoria) {
this.categoria = categoria;
}
public Ecosistema getEcosistema() {
return ecosistema;
}
public void setEcosistema(Ecosistema ecosistema) {
this.ecosistema = ecosistema;
}
public LocalDateTime getCreadoEn() {
return creadoEn;
}
public void setCreadoEn(LocalDateTime creadoEn) {
this.creadoEn = creadoEn;
}
public OffsetDateTime getModificadoEn() {
return modificadoEn;
}
public void setModificadoEn(OffsetDateTime modificadoEn) {
this.modificadoEn = modificadoEn;
}
// toString
@Override
public String toString() {
return this.categoria;
}
}
Bastante similar a la clase anterior, a excepcion de que aca tenemos una llave foranea, para definir ese campo y mapearla en nuestra clase se define como tipo de dato el nombre de la clase, en este caso es Ecosistema ecosistema, con eso ya podemos hacer la relacion en forma de objeto de nuestras entidades de la base de datos.
Hasta acá ya tenemos nuestras entidades del dominio en forma de objeto, continuaremos con la implementacion de la Interface.
Implementación
Empezaremos a implementar nuestra Interface, para ello nos ubicamos en el package com.yourname.nameproject.repository.impl y crearemos dos clases llamadas EcosistemaDAO & CategoriaDAO.
Puedes nombrar a los archivos de esa forma, ó, lo recomendable seria nombrarlos como JdbcEcosistemaRepository ó también como EcosistemaRespository.
Le damos en "next" y nos creara las clases... aca implementaremos nuestra Interface.
Aca empezaremos a hacer la implementacion, empezando por EcosistemaDAO:
public class EcosistemaDAO implements Repository<Ecosistema> {
}
Delante del nombre de la clase definimos implements seguido del nombre de la Interface del Repository, en este caso se llama "Repository<>", aca entre los simbolos "<>" colocamos el nombre del objeto "Ecosistema", aqui es donde el tipo de dato generico que habiamos definido nos sirve para cambiarlo por el nombre del objeto al cual implementaremos los metodos de nuestra Interface del Repository.
Al hacerlo, netbeans nos marcar un error:
Le damos clic en el icono que sale del lado izquierdo de la pantalla, y seleccionamos la opcion Implement all abstract methods, y nos creara los metodos que definimos en nuestra Interface:
public class EcosistemaDAO implements Repository<Ecosistema> {
@Override
public List<Ecosistema> findAll() {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public Ecosistema getById(Integer id) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void save(Ecosistema t) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void delete(Integer id) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
}
Automaticamente netbeans nos coloca los métodos listos para implementar la lógica de como se manejaran los datos, es decir, conectarnos a la base de datos y ejecutar sentencias SQL para traer los datos y poderlos mostrar, como es el caso del método findAll() que nos devuelve una lista con todos los registros de la entidad Ecosistema convertida en objeto.
Continuaremos con la implementacion con CategoriaDAO, siguiendo los mismos pasos, nos queda de la siguiente manera:
public class CategoriaDAO implements Repository<Categoria> {
@Override
public List<Categoria> findAll() {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public Categoria getById(Integer id) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void save(Categoria t) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
@Override
public void delete(Integer id) {
throw new UnsupportedOperationException("Not supported yet."); // Generated from nbfs://nbhost/SystemFileSystem/Templates/Classes/Code/GeneratedMethodBody
}
}
De igual manero, el tipo de dato génerico nos ayuda a poder implementar como tipo de dato el objeto "Categoria", asi poder desarrollar la lógica de cada método según la operación SQL que queramos ejecutar.
Invocando los métodos implementados del Repository
Como último paso nos queda llamar a estos metodos y poder mostrar la informacion que nos devuelve cada uno de ellos, estos se invocan desde la clase "Main", instanciando las clases EcosistemaDAO & CategoriaDAO:
public class MiProject {
public static void main(String[] args) {
EcosistemaDAO ecosistema = new EcosistemaDAO();
CategoriaDAO categoria = new CategoriaDAO();
List<Ecosistema> listaEcosistema = ecosistema.findAll();
List<Categoria> listaCategoria = categoria.findAll();
listaEcosistema.forEach(System.out::println);
listaCategoria.forEach(System.out::println);
}
}
En este ejemplo realizamos la instancia de ambas clases, para luego almacenar la informacion que nos devuelve el método findAll() el cual nos retorna una Lista con los datos consultados a la base de datos.
Por ultimo recorremos la Lista con un bucle forEach e imprimimos en consola la información.
En conclusión, de esta forma se puede implementar estos patrones desarrollando proyectos y ponerlos en práctica teniendo en cuenta que debes crear y desarrollar una base de datos y empezar a practicar y entender la lógica que conlleva aplicar estos patrones, sin antes mencionar que debes aprender a realizar operaciones SQL con JDBC desde JAVA, a continuacion te dejo un enlace a una introducción a JDBC con JAVA
...











Top comments (0)