Mostrando entradas con la etiqueta Cliente-Servidor. Mostrar todas las entradas
Mostrando entradas con la etiqueta Cliente-Servidor. Mostrar todas las entradas

SEPARATA DE JAVA CLIENTE SERVIDOR

JAVA CLIENTE SERVIDOR - JDBC
PRESENTACIÓN

Pretender hacer la programación una actividad muy rentable, implica elegir bien el lenguaje, pienso que Java es una excelente elección.

Java lo utilizan las empresas mas grandes del mundo para desarrollar el core de sus negocios, por ejemplo, las empresas de telecomunicación, los bancos, empresas industriales, etc.

En este manual encontrarás información importante para poder programar bases de datos con JDBC. Este es el material que utilizo en el curso que imparto en SistemasUNI.

MANUAL
CÓDIGO FUENTE

En esta sección te presento un video de una aplicación CLIENTE-SERVIDOR.

Tú tienes acceso al código fuente de esta aplicación, después del video esta el enlace.




PROGRAMANDO PENSANDO EN SERVICIOS - Parte 2

PROGRAMANDO PENSANDO EN SERVICIOS – EJEMPLO 1
EJEMPLO 1
Este primer ejemplo tiene como finalidad entender el concepto de programación en capas y programar pensando en servicios.
REQUERIMIENTO
Crear un programa para calcular la suma y el producto de dos números.
ANÁLISIS
Se necesita un componente con dos servicios:
  1. Calcular la suma de dos números.
  2. Calcular el producto de dos números.
IMPLEMENTACIÓN
En el próximo articulo estare desarrollando el patrón DTO.


CODIGO FUENTE
En esta sección te presento un video que una aplicación CLIENTE-SERVIDOR.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



PROGRAMANDO PENSANDO EN SERVICIOS – Parte 1

PROGRAMANDO PENSANDO EN SERVICIOS – PARTE 1
PENSANDO EN SERVICIOS
Como docente de programación, una de las preguntas que los estudiantes realizan con mucha frecuencia es:
¿Cómo empiezo el proyecto?
La mayoría que se inicia en programación, como es lógico, no tiene claro cómo debe iniciar su proyecto, esto se complica aún más cuando su primer profesor le indica que realice una ventana, y para programarla debe hacer doble click en el botón y empiece a programar.
Pienso, que una parte del problema está en que lo primero que se enseña a los futuros programadores es poner el código de la lógica de un requerimiento en el evento click de un botón, por lo tanto, creen que es así como se debe programar todas las ventanas que requiere su aplicación.
Este estilo de programación no creo que sea el más adecuado, tiene muchos problemas, como por ejemplo:
  1. Repites bloques de código en varias partes de tu aplicación, esto dificulta su mantenimiento.
  2. El mantenimiento de la aplicación rápidamente se vuelve complicado, en muy poco tiempo, tu aplicación se parece más al juego de Jenga.
  3. Escalar tu aplicación, por ejemplo, de Cliente-Servidor a Web se hace prácticamente imposible.
  4. Si cuando estas a la mitad de un proyecto, te cambian de motor de base de datos, actualizar el código se hace una tarea muy complicada.
Voy hacer referencia a Danny Thorpe:
Programar sin una arquitectura en mente es como explorar una gruta sólo con una linterna: no sabes dónde estás, dónde has estado ni a dónde vas.
Pienso que primero debemos pensar en una arquitectura, por ejemplo, pensar en dos capas, una capa de servicios (service) donde se implemente la solución del problema a resolver, y una capa para la interfaz de usuario (view).
Pensar en una capa de servicios para implementar la solución de un requerimiento o problema da muchas ventajas, entre las cuales tenemos:
  1. Permite concentrarnos en la solución.
  2. Facilita las pruebas, algo que no debes dejar de hacer.
  3. Tu solución puedes escalarla fácilmente.
  4. El mantenimiento del código es más fácil.
En el siguiente artículo estaré desarrollando un ejemplo ilustrativo.


CODIGO FUENTE
En esta sección te presento un video que una aplicación CLIENTE-SERVIDOR.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



JAVA JDBC: ResultSet to List

JAVA JDBC: ResultSet to List
INTRODUCCIÓN
Cuando desarrollamos una aplicación con JDBC, una de las tareas que programamos frecuentemente es pasar un objeto de tipo ResultSet a una lista de objetos Map, List<Map<String,Object>>.
Por ejemplo, cuando queremos hacer una consulta a varias tablas, luego el resultado se debe mostrar en una tabla o quisas en un reporte con Jasper Report.
En este oportunidad desarrollara la clase JdbcUtil con un método que permite pasar un objeto ResultSet a una lista, la base de datos a utilizar es EurekaBank.
Las pruebas se realizan con 3 motores de bases de datos diferentes: Oracle, MySQL y SQL Server.
La base de datos la puede descargar desde:
METADATA DEL ResultSet
Para acceder a la metadata de un objeto ResultSet se utiliza el metodo getMetaData(), para obtener la cantidad de columnas se utiliza el método getColumnCount() de la metadata, para obtener el nombre de la columna se utiliza el método getColumnName(i) de la metadata, para obtener la etiqueta de la columna se utiliza el método getColumnLabel(i) de la metadata, siendo i el número de la columna e inicia en 1.
PRUEBA CON ORACLE
La versión de Oracle utilizada es la 11.2 y el driver jdbc utilizado es ojdbc6.jar.:
SQL> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Express Edition Release 11.2.0.2.0 - Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for 32-bit Windows: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
El código base a utilizar es:
// Datos Oracle
String driver = "oracle.jdbc.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
String user = "eureka";
String pass = "admin";
// Conexión
Class.forName(driver).newInstance();
cn = DriverManager.getConnection(url, user, pass);
// Consulta
String sql = "aquí debe ir la consulta";
PreparedStatement pstm = cn.prepareStatement(sql);
ResultSet rs = pstm.executeQuery();
// Obtener metadata
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
System.out.println("getColumnName()\tgetColumnLabel()");
for (int i = 1; i <= columns; i++) {
  System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i));
}
rs.close();
pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo, vch_cliepaterno, 
  vch_cliematerno, vch_clienombre 
from cliente
El resultado es el siguiente:
getColumnName()  getColumnLabel()
CHR_CLIECODIGO   CHR_CLIECODIGO
VCH_CLIEPATERNO  VCH_CLIEPATERNO
VCH_CLIEMATERNO  VCH_CLIEMATERNO
VCH_CLIENOMBRE   VCH_CLIENOMBRE
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo cod, vch_cliepaterno pat, 
  vch_cliematerno mat, vch_clienombre nom
from cliente
El resultado es el siguiente:
getColumnName()   getColumnLabel()
COD               COD
PAT               PAT
MAT               MAT
NOM               NOM
Consultando dos tablas
La consulta a utilizar es la siguiente:
select 
  tm.vch_tipodescripcion tipo,
  sum(m.dec_moviimporte) importe
from tipomovimiento tm join movimiento m
on tm.chr_tipocodigo = m.chr_tipocodigo
group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName()   getColumnLabel()
TIPO              TIPO
IMPORTE           IMPORTE
De los resultados obtenidos se puede concluir que tanto getColumnName() y getColumnLabel() arrojan los mismos valores, se puede utilizar cualquiera de los dos métodos.
PRUEBA CON MYSQL
La versión de MySQL utilizada es la 5.6 y el driver jdbc utilizado es la versión 5.1.23:
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.12-log MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective owners.
El código base a utilizar es:
// Datos MySQL
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/EUREKABANK";
String user = "eureka";
String pass = "admin";
// Conexión
Class.forName(driver).newInstance();
cn = DriverManager.getConnection(url, user, pass);
// Consulta
String sql = "aquí debe ir la consulta";
PreparedStatement pstm = cn.prepareStatement(sql);
ResultSet rs = pstm.executeQuery();
// Obtener metadata
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
System.out.println("getColumnName()\tgetColumnLabel()");
for (int i = 1; i <= columns; i++) {
  System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i));
}
rs.close();
pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo, vch_cliepaterno, 
  vch_cliematerno, vch_clienombre 
from cliente
El resultado es el siguiente:
getColumnName()   getColumnLabel()
chr_cliecodigo    chr_cliecodigo
vch_cliepaterno   vch_cliepaterno
vch_cliematerno   vch_cliematerno
vch_clienombre    vch_clienombre
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo cod, vch_cliepaterno pat, 
  vch_cliematerno mat, vch_clienombre nom
from cliente
El resultado es el siguiente:
getColumnName()    getColumnLabel()
chr_cliecodigo     cod
vch_cliepaterno    pat
vch_cliematerno    mat
vch_clienombre     nom
Consultando dos tablas
La consulta a utilizar es la siguiente:
select 
  tm.vch_tipodescripcion tipo,
  sum(m.dec_moviimporte) importe
from tipomovimiento tm join movimiento m
on tm.chr_tipocodigo = m.chr_tipocodigo
group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName()        getColumnLabel()
vch_tipodescripcion    tipo
importe                importe
De los resultados obtenidos se puede concluir que getColumnLabel() sería la opción mas conveniente a utilizar.
PRUEBA CON SQL SERVER
La versión de SQL Server utilizada es la 2008 R2 y el driver jdbc utilizado es JTDS versión 1.2.5:
Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (X64) 
Apr  2 2010 15:48:46 
Copyright (c) Microsoft Corporation
Enterprise Edition (64-bit) on Windows NT 6.1  (Build 7601: Service Pack 1)
El código base a utilizar es:
// Datos SQL Server
String driver = "net.sourceforge.jtds.jdbc.Driver";
String url = "jdbc:jtds:sqlserver://localhost:1433/EUREKABANK";
String user = "sa";
String pass = "sql";
// Conexión
Class.forName(driver).newInstance();
cn = DriverManager.getConnection(url, user, pass);
// Consulta
String sql = "aquí debe ir la consulta";
PreparedStatement pstm = cn.prepareStatement(sql);
ResultSet rs = pstm.executeQuery();
// Obtener metadata
ResultSetMetaData md = rs.getMetaData();
int columns = md.getColumnCount();
System.out.println("getColumnName()\tgetColumnLabel()");
for (int i = 1; i <= columns; i++) {
  System.out.println(md.getColumnName(i) + "\t" + md.getColumnLabel(i));
}
rs.close();
pstm.close();
Consultando un tabla
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo, vch_cliepaterno, 
  vch_cliematerno, vch_clienombre 
from cliente
El resultado es el siguiente:
getColumnName()    getColumnLabel()
chr_cliecodigo     chr_cliecodigo
vch_cliepaterno    vch_cliepaterno
vch_cliematerno    vch_cliematerno
vch_clienombre     vch_clienombre
Cambiando el titulo de las columnas
La consulta a utilizar es la siguiente:
select 
  chr_cliecodigo cod, vch_cliepaterno pat, 
  vch_cliematerno mat, vch_clienombre nom
from cliente
El resultado es el siguiente:
getColumnName()    getColumnLabel()
cod                cod
pat                pat
mat                mat
nom                nom
Consultando dos tablas
La consulta a utilizar es la siguiente:
select 
  tm.vch_tipodescripcion tipo,
  sum(m.dec_moviimporte) importe
from tipomovimiento tm join movimiento m
on tm.chr_tipocodigo = m.chr_tipocodigo
group by tm.vch_tipodescripcion
El resultado es el siguiente:
getColumnName()        getColumnLabel()
vch_tipodescripcion    tipo
importe                importe
De los resultados obtenidos se puede concluir que ambos metodos arrojan los mismos resultados, por lo tanto, se puede utilizar cualquiera de los dos.
CLASE UTILITARIA
A continuación tenemos la clase propuesta para pasar un objeto ResultSet a una List<Map<String,?>>.
package pe.egcc.app.util;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Eric Gustavo Coronel Castillo
 * @blog gcoronelc.blogspot.com
 */
public final class JdbcUtil {

  private JdbcUtil() {
  }

  public static List<Map<String, ?>> rsToList(ResultSet rs) throws SQLException {
    ResultSetMetaData md = rs.getMetaData();
    int columns = md.getColumnCount();
    List<Map<String, ?>> results = new ArrayList<Map<String, ?>>();
    while (rs.next()) {
      Map<String, Object> row = new HashMap<String, Object>();
      for (int i = 1; i <= columns; i++) {
        row.put(md.getColumnLabel(i).toLowerCase(), rs.getObject(i));
      }
      results.add(row);
    }
    return results;
  }

}
A continuación se tiene un ejemplo de como utilizar esta clase:
 
List<Map<String,?>> lista = JdbcUtil.rsToList(rs);
 
Siendo rs un objeto ResultSet.
Puede descargar el proyecto desde el siguiente enlace:
Descargar Proyecto
CÓDIGO FUENTE
En esta sección te presento un video que una aplicación CLIENTE-SERVIDOR desarrollada con Java y Oracle.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



SQL SERVER - COPIAS DE SEGURIDAD

SQL SERVER - COPIAS DE SEGURIDAD

INTRODUCCIÓN

En esta oportunidad les traigo una guía práctica para crear copias de seguridad y sus restauración utilizando diferentes situaciones.

GUIA

CÓDIGO FUENTE - EUREKA-WEB-ORACLE-JDBC

En esta oportunidad te presento un video donde te explico cómo ejecutar el código fuente de una aplicación Java Web, utilizando HTML, CSS, JavaScript, AJAX y JSON, en la capa de persistencia se utiliza JDBC y base de datos Oracle XE 11g.

Tú tienes acceso al código fuente de esta aplicación, después del video esta el enlace.



ORACLE SQL - CONSULTAS BASICAS

ORACLE SQL - CONSULTAS BASICAS - GUSTAVO CORONEL
TALLER ORACLE SQL - LECCIÓN 02

El tema a desarrollar en esta oportunidad es CONSULTAS BÁSICAS.

PROGRAMACIÓN DE BASES DE DATOS ORACLE CON JAVA JDBC

Aprenderás a aplicar correctamente el API JDBC de Java para programar bases de datos ORACLE.
Aprenderás los conceptos fundamentales de Oracle Database y a crear el esquema de trabajo que se utilizará durante el curso.
Estarás capacitado para aplicar el API JDBC de Java para ejecutar consultas sin parámetros, consultas con parámetros, gestión de transacciones y ejecutar procedimientos almacenados que retornan cursor y que gestionan transacciones.
Estarás capacitado para desarrollar una aplicación de escritorio empresarial que ayude a las empresas a gestionar sus procesos comerciales.
Cupón de descuento: JDBCORACLE10


ORACLE SQL - INTRODUCCION

ORACLE SQL - INTRODUCCION

Primera lección del taller ORACLE SQL.

El taller se esta desarrollando con la versión 11g con Windows Server 2008.

CÓDIGO FUENTE - EUREKA-WEB-ORACLE-JDBC

En esta oportunidad te presento un video donde te explico cómo ejecutar el código fuente de una aplicación Java Web, utilizando HTML, CSS, JavaScript, AJAX y JSON, en la capa de persistencia se utiliza JDBC y base de datos Oracle XE 11g.

Tú tienes acceso al código fuente de esta aplicación, después del video esta el enlace.



CREACIÓN DEL ESQUEMA EUREKA

SQL SERVER ORACLE MYSQL JAVA JAVAEE JDBC MVC DAO PATRONES ANDROID SERVLETS JSP

EUREKABANK DATABASE

El esquema de datos EUREKA lo utilizo en mis cursos de Java y Oracle, por tal motivo recibo constantemente preguntas de como crearlo.

En esta guía encontrara paso a paso, como crear el esquema EUREKA, desde la instalación de Oracle 10g XE.

CÓDIGO FUENTE - EUREKA-WEB-ORACLE-JDBC

En esta oportunidad te presento un video donde te explico cómo ejecutar el código fuente de una aplicación Java Web, utilizando HTML, CSS, JavaScript, AJAX y JSON, en la capa de persistencia se utiliza JDBC y base de datos Oracle XE 11g.

Tú tienes acceso al código fuente de esta aplicación, después del video esta el enlace.



Java OO - Lección 08 - Colecciones

Cliente-Servidor, DAO, Eclipse, GlassFish, Java, Java POO, JAVA SERVER FACES, Java Web, JEE, JFreeChart, Patrones, POO, Tomcat, Web, Colecciones
JAVA POO - LECCION 08 - COLECCIONES

INTRODUCCIÓN

Las colecciones son un conjunto de interfaces, clases abstractas y clases concretas que te permiten manejar una gran cantidad de datos relacionados en forma de listas para lo cual dispones de la interfaz List y la clase ArrayList, también como pares de datos CLAVE->VALOR para los cual dispones de la interfaz Map y la clase HashMap.
Todas las clases que nos permiten manejas conjuntos de datos se agrupan en un marco de trabajo conocido como Java Colecction Framework (JCF), y entre sus características la que mas resalta es que soporte Generics, esto quiere decir que podemos crear por ejemplo lista genéricas de tipo Object o listas personalizadas, por ejemplo de tipo Producto, Cliente, Cuenta, etc.
Una de sus aplicación la tenemos en la capa DAO, por ejemplo, si estamos consultan los productos de una categoría, la capa DAO estaría retornando una lista con objetos de tipo Producto.
Todos los componentes de JCF se encuentran en el paquete java.util.

DIAPOSITIVA

PRESENTACIÓN DEL TEMA

CURSO PROFESIONAL DE JAVA ORIENTADO A OBJETOS

En esta sección te presento el curso virtual de JAVA ORIENTADO A OBJETOS.

CODIGO FUENTE - EUREKA-WEB-MYSQL-SPRING

En esta sección te presento un video de una aplicación web desarrollada SPRING FRAMEWORK y MYSQL.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.



Resumen Seminario Java Cliente-Servidor

SEMINARIO CLIENTE - SERVIDOR CON JAVA
PARTE I - CONOCIENDO AL MONSTRUO
Cliente-Servidor: Aclarando Conceptos
Cliente-Servidor
Es un modelo basado en la cooperación e interacción de dos partes conocidas como servidor o back-end y cliente o front-end.
Aplicación Servidor
Es la aplicación que provee servicios, es la aplicación que provee los servicios; por ejemplo, los servidores de base de datos ofrecen servicios de persistencia de datos, podríamos mencionar a SQL Server, Oracle, MySQL, etc,
Aplicación Cliente
Es la aplicación que hace uso o consume los servicios de la Aplicación Servidor; por ejemplo, las aplicaciones comerciales como los sistemas de ventas y compras necesitan que sus datos persistan en el tiempo, para lo cual se recurren a los servidores de base de datos que ofrecen estos servicios.
Arquitectura Cliente-Servidor
El cliente se encuentra del lado del usuario y se define como un proceso consumidor de servicios, mientras que el servidor provee los servicios requeridos y se encuentra de manera remota al usuario y es transparente al cliente.
Los clientes deben estar en la red de la empresa, estas pueden ser redes locales, pero también es posible tener clientes remotos a través por ejemplo de una red VPN.
El API JDBC: Implementaciones
API JDBC
Esta API está compuesta por un conjunto de clases e interfaces que estandarizan el acceso a las bases de datos. Gracias a la utilización de JDBC, un programa Java puede acceder a cualquier base de datos sin necesidad de modificar la aplicación. Sin embargo, para que esto sea posible es necesario que el fabricante ofrezca un driver que cumpla la especificación JDBC.
Tipos de Driver
Tenemos cuatro tipos de driver:
  • Tipo 1: JDBC-ODBC bridge driver
  • Tipo 2: Native API/Partly Java Driver
  • Tipo 3: Pure Java Driver
  • Tipo 4: Native Protocol Java Driver
Tipo 1: JDBC-ODBC bridge driver
Permite utilizar drivers ODBC, su desventaja es que se debe instalar el driver ODBC en cada cliente.
Tipo 2: Native API/Partly Java Driver
Requiere que se instalen las librerías nativas en cada cliente.
Tipo 3: Pure Java Driver
Este tipo de driver traduce llamadas JDBC en un protocolo de red independiente del DBMS y luego, a un protocolo de DBMS.
Un Servidor JDBC, realiza la tarea de middleware, siendo capaz de conectar un cliente Java a diferentes bases de datos.
Tipo 4: Native Protocol Java Driver
El driver tipo 4 convierte llamadas JDBC directamente en el protocolo de red usado por el DBMS. Esto permite llamadas directas desde la máquina del cliente al servidor del DBMS, es una solución muy práctica y la más utilizada.
El API JDBC: Componentes Principales
Objeto: Connection
Establece la conexión con la base de datos y maneja las transacciones.
Objeto: Statement
Se utiliza para ejecutar sentencias sin parámetros.
Objeto: PreparedStatement
Se utiliza para ejecutar sentencias con parámetros.
Objeto: CallableStatement
Se utiliza para ejecutar procedimientos almacenados.
Objeto ResultSet
Se utiliza para procesar resultados.
Estrategias para programar transacciones
Controladas desde el cliente
En este caso desde la aplicación java programamos el inicio y fin de la transacción.
Controladas en la base de datos
En este caso programamos la transacción en el procedimiento almacenado.
El patrón DAO
Desarrollo Clásico
En el objeto de negocio se programa la lógica de negocio y la lógica de persistencia, haciendo difícil su mantenimiento.
Patrón DAO – División en Capas
El patrón DAO permite dividir en capas separadas la lógica de negocio y la lógica de persistencia.
Patrón DAO – Estructura
La capa de negocio hace uso de la capa de persistencia, y para que se comuniquen los datos se utilizan objetos Transfer Object (TO), también denominados Data Transfer Object (DTO).
Por ejemplo, si se consulta los datos de un cliente, el objeto DAO devolverá un objeto TO con los datos del cliente. Si se consulta los artículos de una categoría, el objeto DAO devolverá una colección de objetos TO de tipo Artículo.
Patrón DAO – Diagrama se secuencia
En el diagrama de secuencia se puede apreciar la responsabilidad de cada capa, la capa Data Source puede ser un motor de base de datos, como por ejemplo Oracle, MySQL o SQL Server.
PARTE II - DOMINANDO AL MONSTRUO
Modelo de Datos
Creación del Esquema de Datos
El siguiente video ilustra la creación del esquema VENTAS.
Conexión con la Fuente de Datos
public class AccesoDB {

    private AccesoDB() {
    }

    public static Connection getConnection() throws SQLException{
        Connection cn = null;
        try {
            // --------------------------------------------------
            // Paso 1: Cargar el driver a memoria
            Class.forName("oracle.jdbc.OracleDriver").newInstance();
            // Paso 2: Obtener el objeto Connection
            String url = "jdbc:oracle:thin:@localhost:1521:XE";
            cn = DriverManager.getConnection(url, "ventas", "admin");
            // --------------------------------------------------
        } catch (SQLException e) {
            throw e;
        } catch(ClassNotFoundException e){
            throw new SQLException("No se encontró el driver de la base de datos.");
        } catch(Exception e){
            throw new SQLException("No se puede establecer la conexión con la base de datos.");
        }
        return cn;
    }
}
Implementación de un CRUD
Para la demostración se implementa el CRUD para la tabla PRODUCTO.
Interfaz
public interface ProductoDao {

  /**
   * Transacción controlada desde el cliente
   *
   * @param prod
   */
  void create1(Producto prod);

  /*
   * Transacción controlada en la Base de Datos
   */
  void create2(Producto prod);

  List readAll();

  Producto readForId(int id);

  List readForName(String name);

  void update(Producto prod);

  void delete(int id);
}  
Plantilla para las Consultas
Connection cn = null;
try {
  cn = AccesoDB.getConnection();

  // Consulta
  
} catch (SQLException e) {
    throw new RuntimeException(e.getMessage());
} catch (Exception e) {
  throw new RuntimeException("Error bla bla bla.");
} finally {
  try {
    cn.close();
  } catch (Exception e) {
  }
}
Plantilla para Transacción Desde el Cliente
Connection cn = null;
try {
  cn = AccesoDB.getConnection();
  cn.setAutoCommit(false); // Inicia Tx
  
  // Proceso
  
  cn.commit(); // Confirmar Tx
} catch (SQLException e) {
  try { cn.rollback(); } catch (Exception e1) { }
  throw new RuntimeException(e.getMessage());
} catch (Exception e) {
  try { cn.rollback(); } catch (Exception e1) { }
  throw new RuntimeException("Error bla bla bla.");
} finally {
  try { 
    cn.close(); 
  } catch (Exception e) { }
}
Plantilla para Transacción Desde la Base de Datos
Connection cn = null;
try {
  cn = AccesoDB.getConnection();
  cn.setAutoCommit( true ); 
  
  // Ejecución de procedimiento almacenado
  
} catch (SQLException e) {
  throw new RuntimeException(e.getMessage());
} catch (Exception e) {
  throw new RuntimeException("Error bla bla bla.");
} finally {
  try { 
    cn.close(); 
  } catch (Exception e) { }
}
Implementación
public class OracleProductoDao implements ProductoDao {

  /**
   * Control de transacción desde el cliente
   * @param prod 
   */
    @Override
    public void create1(Producto prod) {
        Connection cn = null;
        try {
            // Variables
      Statement stm;
      PreparedStatement pstm;
            String query;
            int id;
            ResultSet rs;
            // Conexión
            cn = AccesoDB.getConnection();
            // Iniciar la Tx
            cn.setAutoCommit(false);
            // Obtener el Id del producto
            query = "select sq_producto.NextVal id from dual";
            stm = cn.createStatement();
            rs = stm.executeQuery(query);
            rs.next();
            id = rs.getInt("id");
            // Insertar el producto
            query = "insert into producto"
                    + "(idprod,idcat,nombre,precio,stock) "
                    + "values(?,?,?,?,?) ";
            pstm = cn.prepareStatement(query);
            pstm.setInt(1, id);
            pstm.setInt(2, prod.getIdcat());
            pstm.setString(3, prod.getNombre());
            pstm.setDouble(4, prod.getPrecio());
            pstm.setInt(5, prod.getStock());
            pstm.executeUpdate();
            // Retornar el id
            prod.setIdprod(id);
            // Confirmar Tx
            cn.commit();
            // Cerrar objetos
            rs.close();
            stm.close();
            pstm.close();
        } catch (SQLException e) {
            try {
                cn.rollback();
            } catch (Exception e1) {
            }
            throw new RuntimeException(e.getMessage());
        } catch (Exception e) {
            try {
                cn.rollback();
            } catch (Exception e1) {
            }
            throw new RuntimeException("Error en el proceso crear producto.");
        } finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
    }

  /**
   * Control de transacción en el procedimiento almacenado
   * @param prod 
   */
    @Override
    public void create2(Producto prod) {
        Connection cn = null;
        try {
            cn = AccesoDB.getConnection();
            cn.setAutoCommit(true);
            String query = "{call usp_crea_producto(?,?,?,?,?)}";
            CallableStatement cstm = cn.prepareCall(query);
            cstm.registerOutParameter(1, Types.INTEGER);
            cstm.setInt(2, prod.getIdcat());
            cstm.setString(3, prod.getNombre());
            cstm.setDouble(4, prod.getPrecio());
            cstm.setInt(5, prod.getStock());
            cstm.executeUpdate();
            prod.setIdprod(cstm.getInt(1));
            cstm.close();
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException("No se puede crear el producto.");
        } finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public List readAll() {
        List lista = new ArrayList();
        Connection cn = null;
        try {
            cn = AccesoDB.getConnection();
            String query = "select idprod, idcat, nombre, precio, stock "
                    + "from producto ";
            Statement stm = cn.createStatement();
            ResultSet rs = stm.executeQuery(query);
            while (rs.next()) {
                Producto o = rsToBean(rs);
                lista.add(o);
            }
            rs.close();
            stm.close();
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage());
        } catch(Exception e){
            throw new RuntimeException("No se puede consultar la base de datos.");
        }finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
        return lista;
    }

    @Override
    public Producto readForId(int id) {
        Producto o = null;
        Connection cn = null;
        try {
            cn = AccesoDB.getConnection();
            String query = "select idprod, idcat, nombre, precio, stock "
                    + "from producto "
                    + "where idprod = ?";
            PreparedStatement pstm = cn.prepareStatement(query);
            pstm.setInt(1, id);
            ResultSet rs = pstm.executeQuery();
            if (rs.next()) {
                o = rsToBean(rs);
            }
            rs.close();
            pstm.close();
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException("Error en la lectura del producto.");
        } finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
        return o;
    }

    @Override
    public List readForName(String name) {
        List lista = new ArrayList();
        Connection cn = null;
        try {
            cn = AccesoDB.getConnection();
            String query = "select idprod, idcat, nombre, precio, stock "
                    + "from producto "
                    + "where upper(nombre) like ?";
            PreparedStatement pstm = cn.prepareStatement(query);
            name = "%" + name.toUpperCase() + "%";
            pstm.setString(1, name);
            ResultSet rs = pstm.executeQuery();
            while (rs.next()) {
                Producto o = rsToBean(rs);
                lista.add(o);
            }
            rs.close();
            pstm.close();
        } catch (SQLException e) {
            throw new RuntimeException(e.getMessage());
        } catch(Exception e){
            throw new RuntimeException("No se puede consultar la base de datos.");
        } finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
        return lista;
    }

    @Override
    public void update(Producto prod) {
    Connection cn = null;
        try {
            // Variables
            PreparedStatement pstm;
            String query;
            int filas;
            // Conexión
            cn = AccesoDB.getConnection();
            // Iniciar la Tx
            cn.setAutoCommit(false);
            // Insertar el producto
            query = "update producto set idcat=?, nombre=?, precio=?, "
              + "stock=? where idprod = ? ";
            pstm = cn.prepareStatement(query);
            pstm.setInt(1, prod.getIdcat());
            pstm.setString(2, prod.getNombre());
            pstm.setDouble(3, prod.getPrecio());
            pstm.setInt(4, prod.getStock());
            pstm.setInt(5, prod.getIdprod());
            filas = pstm.executeUpdate();
            if(filas == 0){
              throw new SQLException("Producto no existe.");
            }
            // Confirmar Tx
            cn.commit();
            // Cerrar objetos
            pstm.close();
        } catch (SQLException e) {
            try {
                cn.rollback();
            } catch (Exception e1) {
            }
            throw new RuntimeException(e.getMessage());
        } catch (Exception e) {
            try {
                cn.rollback();
            } catch (Exception e1) {
            }
            throw new RuntimeException("Error en el proceso crear producto.");
        } finally {
            try {
                cn.close();
            } catch (Exception e) {
            }
        }
    }

    @Override
    public void delete(int id) {
      Connection cn = null;
      String query;
      PreparedStatement pstm;
      ResultSet rs;
      int cont;
      try {
        cn = AccesoDB.getConnection();
        cn.setAutoCommit(false);
        // Verificar si el producto rgistra ventas
        query = "select count(*) cont from detalle where idprod = ?";
        pstm = cn.prepareStatement(query);
        pstm.setInt(1, id);
        rs = pstm.executeQuery();
        rs.next();
        cont = rs.getInt("cont");
        rs.close();
        pstm.close();
        if (cont > 0) {
          throw new SQLException("El producto registra ventas, no se puede eliminar.");
        }
        // Eliminar el producto
        query = "delete from producto where idprod=?";
        pstm = cn.prepareStatement(query);
        pstm.setInt(1, id);
        int filas = pstm.executeUpdate();
        if (filas == 0) {
          throw new SQLException("Código de producto no existe, "
              + "posiblemente fue eliminado por otro usuario.");
        }
        cn.commit();
        pstm.close();
      } catch (SQLException e) {
        try {
          cn.rollback();
        } catch (Exception e1) {
        }
        throw new RuntimeException(e.getMessage());
      } catch (Exception e) {
        try {
          cn.rollback();
        } catch (Exception e1) {
        }
        throw new RuntimeException("Error al tratar de eliminar el producto.");
      } finally {
        try {
          cn.close();
        } catch (Exception e) {
        }
      }
    }

    private Producto rsToBean(ResultSet rs) throws SQLException {
        Producto o = new Producto();
        o.setIdprod(rs.getInt("idprod"));
        o.setIdcat(rs.getInt("idcat"));
        o.setNombre(rs.getString("nombre"));
        o.setPrecio(rs.getDouble("precio"));
        o.setStock(rs.getInt("stock"));
        return o;
    }
  
}
Video
El siguiente video muestra el funcionamiento del CRUD de la tabla PRODUCTO.

Programación de Procesos de Negocio
Aclarando Conceptos
  • Esta compuesto por varias operaciones que deben trabajar como una sola unidad indivisible.
  • Cada proceso corresponde a un servicio de la capa de negocio.
  • La lógica de persistencia se debe manejar como una transacción y corresponde a un servicio de la capa DAO.
  • Por ejemplo, grabar una venta, es un proceso que involucra varias operaciones que se deben ejecutar como una unidad indivisible.
Interfaz
public interface VentasDao {
  
  void grabarVenta( VentaDto ventaDto);
}
Implementación
public class OracleVentasDao implements VentasDao{

  @Override
  public void grabarVenta(VentaDto ventaDto) {
    Connection cn = null;
    try {
      cn = AccesoDB.getConnection();
      // Inicindo la Tx
      cn.setAutoCommit(false);
      // Obtener el idventa
      String query = "select sq_venta.nextval id from dual";
      Statement stm = cn.createStatement();
      ResultSet rset = stm.executeQuery(query);
      rset.next();
      int idventa = rset.getInt("id");
      // Grabar venta
      query = "insert into venta(IDVENTA,CLIENTE,IDEMP,"
              + "FECHA,IMPORTE) values(?,?,?,sysdate,?)";
      PreparedStatement pstm = cn.prepareStatement(query);
      pstm.setInt(1, idventa);
      pstm.setString(2, ventaDto.getCliente());
      pstm.setInt(3, ventaDto.getIdEmpl());
      pstm.setDouble(4, ventaDto.getImporte());
      pstm.executeUpdate();
      // Grabar los detalles
      query = "insert into detalle(IDVENTA,IDPROD,CANT,"
              + "PRECIO,SUBTOTAL) values(?,?,?,?,?)";
      pstm = cn.prepareStatement(query);
      PreparedStatement pstmLeerStock = cn.prepareStatement("select stock from producto where idprod = ? for update");
      PreparedStatement pstmActStock = cn.prepareStatement("update producto set stock = ? where idprod = ?");
      int stock;
      for ( VentaItem item: ventaDto.getDetalle()) {
        // Verificar stock
        pstmLeerStock.setInt(1, item.getIdprod());
        ResultSet rs = pstmLeerStock.executeQuery();
        rs.next();
        stock = rs.getInt("stock");
        rs.close();
        if(stock < item.getCant()){
          throw new SQLException("No existe stock suficiente de " + item.getNombre() + ".");
        }
        // Actualizar stock
        pstmActStock.setInt(1,  stock - item.getCant());
        pstmActStock.setInt(2, item.getIdprod());
        pstmActStock.executeUpdate();
        // Grabar detalle
        pstm.setInt(1, idventa);
        pstm.setInt(2, item.getIdprod());
        pstm.setInt(3, item.getCant());
        pstm.setDouble(4, item.getPrecio());
        pstm.setDouble(5, item.getSubtotal());
        pstm.executeUpdate();
      }
      // Grabar pagos
      /*  Falta implementar */
      
      // confirmar Tx
      cn.commit();
      ventaDto.setIdventa(idventa);
    } catch (SQLException e) {
      try {
        cn.rollback();
      } catch (Exception e1) {
      }
      throw new RuntimeException(e.getMessage());
    } catch (Exception e) {
      try {
        cn.rollback();
      } catch (Exception e1) {
      }
      throw new RuntimeException("Error en el proceso Grabar Venta.");
    } finally {
      try {
        cn.close();
      } catch (Exception e) {
      }
    }
  }
  
}
Video
El siguiente video muestra el funcionamiento del proceso de venta.
DESCARGAR PROYECTO
CODIGO FUENTE
En esta sección te presento un video de una aplicación CLIENTE-SERVIDOR.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.