Mostrando entradas con la etiqueta Access. Mostrar todas las entradas
Mostrando entradas con la etiqueta Access. Mostrar todas las entradas

domingo, 6 de noviembre de 2011

Ejercicio "Efemérides" (base de datos)

Crear una aplicación que permita gestionar una base de datos de efemérides. Todas las operaciones se realizarán mediante consola, ya que el tema de formularios lo hemos empezado a ver después del de acceso a bases de datos.

Para empezar creamos en Access la base de datos "efemerides", que contendrá una única entidad: "efemeride", con los siguientes atributos:
  • id. De tipo entero.
  • texto. De tipo texto.
  • fecha. De tipo fecha.
Una vez creada la base de datos, implementamos el puente JDBC-ODBC y empezamos a trabajar.

Dentro de nuestro proyecto, crearemos la clase "BaseDatos" y el fichero de configuración, que como vimos en la entrada anterior nos facilitan todas las gestiones que realicemos con respecto al acceso a bases de datos.

Además, para que todo sea más realista y más sencillo de entender para el programador, crearemos la clase "Efemeride", que tendrá los atributos propios de una efeméride y, como métodos, los correspondientes "getters" y "setters".

CLASE EFEMERIDE

public class Efemeride {
 private Integer id;
 private String texto;
 private Date fecha;

 public Integer getId() {
  return id;
 }

 public void setId(Integer id) {
  this.id = id;
 }

 public String getTexto() {
  return texto;
 }

 public void setTexto(String texto) {
  this.texto = texto;
 }

 public Date getFecha() {
  return fecha;
 }

 public void setFecha(Date fecha) {
  this.fecha = fecha;
 }
}

TRUCO: una vez que has especificado todos los atributos de una clase, en Eclipse es muy sencillo generar los métodos getAtributo() y setAtributo(Dato dato). Sólo tienes que hacer clic con el botón derecho y en "Source" elegir "Generate Getters and Setters". En el cuadro de diálogo que se abre eliges los atributos de los que quieres generar estos métodos, haces clic en "OK" y ¡listo!

Para controlar las excepciones de nuestra aplicación, crearemos nuestra propia excepción. En nuestro caso esta clase fue facilitada por el profesor, así como una interfaz ("IEfemerides") que debe implementar la clase "Efemerides". Esta clase es la encargada de realizar todas las gestiones con la base de datos (insertar datos, actualizar, recuperar, etc.).

CLASE EFEMERIDEEXCEPTION

public class EfemerideException extends Exception {
 private static final long serialVersionUID = 1L;

 public EfemerideException(String mensaje) {
  super(mensaje);
 }
 
}

CLASE EFEMERIDES

public class Efemerides implements IEfemerides {

 @Override
 public void insertar(Efemeride efemeride) throws EfemerideException {
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "insert into efemerides (texto, fecha) values (?, ?)";
   PreparedStatement insertar = conexion.prepareStatement(sql);

   insertar.setString(1, efemeride.getTexto());
   insertar.setDate(2, DateUtils.convertir(efemeride.getFecha()));

   insertar.executeUpdate();
   insertar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido insertar la efeméride.");
  }
 }

 @Override
 public void eliminar(Integer id) throws EfemerideException {
  try {
   int eliminado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "delete from efemerides where id=?";
   PreparedStatement eliminar = conexion.prepareStatement(sql);

   eliminar.setInt(1, id);

   eliminado = eliminar.executeUpdate();
   if (eliminado == 0) {
    throw new EfemerideException("La efeméride no existe.");
   }
   eliminar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido eliminar la efeméride.");
  }
 }

 @Override
 public void actualizar(Efemeride efemeride) throws EfemerideException {
  try {
   int actualizado;
   Connection conexion = BaseDatos.getConnection();
   String sql = "update efemerides set texto=?, fecha=? where id=?";
   PreparedStatement actualizar = conexion.prepareStatement(sql);

   actualizar.setString(1, efemeride.getTexto());
   actualizar.setDate(2, DateUtils.convertir(efemeride.getFecha()));
   actualizar.setInt(3, efemeride.getId());

   actualizado=actualizar.executeUpdate();
   if (actualizado == 0) {
    throw new EfemerideException("La efeméride no existe, por lo que no se ha podido actualizar.");
   }
   actualizar.close();

  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido actualizar la efeméride.");
  }

 }

 @Override
 public Efemeride recuperar(Integer id) throws EfemerideException {
  Efemeride efemeride = new Efemeride();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where id=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, id);

   ResultSet resultado = recuperar.executeQuery();
   if (!resultado.next()) {
    throw new EfemerideException("La efeméride no se ha recuperado porque no existe.");
   } else {
    efemeride.setId(id);
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se ha podido recuperar la efeméride.");
  }
  return efemeride;
 }

 @Override
 public List<Efemeride> hoy() throws EfemerideException {
  Date hoy = new Date();

  return recuperarPorFecha(hoy);
 }

 @Override
 public List<Efemeride> recuperarTodas() throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   Statement recuperar = conexion.createStatement();

   ResultSet resultado;
   resultado = recuperar.executeQuery("select * from efemerides");

   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

 @Override
 public List<Efemeride> recuperarPorFecha(Date fecha)
   throws EfemerideException {
  List<Efemeride> listado = new ArrayList<Efemeride>();
  try {
   Connection conexion = BaseDatos.getConnection();
   String sql = "select * from efemerides where day(fecha)=? and month(fecha)=?";
   PreparedStatement recuperar = conexion.prepareStatement(sql);

   recuperar.setInt(1, DateUtils.dia(fecha));
   recuperar.setInt(2, DateUtils.mes(fecha));

   ResultSet resultado = recuperar.executeQuery();
   while (resultado.next()) {
    Efemeride efemeride = new Efemeride();
    efemeride.setId(resultado.getInt("id"));
    efemeride.setTexto(resultado.getString("texto"));
    efemeride.setFecha(resultado.getDate("fecha"));
    listado.add(efemeride);
   }
  } catch (SQLException e) {
   e.printStackTrace();
   throw new EfemerideException("No se han podido recuperar las efemérides.");
  }
  return listado;
 }

}

Finalmente, la aplicación con la que interactuará el usuario se creó utilizando varias clases proporcionadas por el profesor, que permitían crear menús y recoger los datos introducidos por el usuario.

CLASE MENUEFEMERIFE

public class MenuEfemeride {

 private static Efemerides efemerides = new Efemerides();
 
 public static void main(String[] args) {

  Menu principal = new Menu("Menú principal. Efemérides");
  Menu consultar = new Menu("Consultar");
  
  Accion insertarEfemeride = new Accion("Insertar efeméride") {
   public void accion() { onInsertarEfemeride(); }
  };
  Accion eliminarEfemeride = new Accion("Eliminar efeméride") {
   public void accion() { onEliminarEfemeride(); }
  };
  Accion actualizarEfemeride = new Accion("Actualizar efeméride") {
   public void accion() { onActualizarEfemeride(); }
  };
  Accion buscarPorId = new Accion("Buscar efeméride por identificador") {
   public void accion() { onBuscarPorId(); }
  };
  Accion buscarPorFecha = new Accion("Buscar efeméride por fecha") {
   public void accion() { onBuscarPorFecha(); }
  };
  Accion efemeridesHoy = new Accion("Efemérides de hoy") {
   public void accion() { onEfemeridesHoy(); }
  };
  Accion todas = new Accion("Todas las efemérides") {
   public void accion() { onTodas(); }
  };
  
  consultar.agregar(buscarPorId);
  consultar.agregar(buscarPorFecha);
  consultar.agregar(efemeridesHoy);
  consultar.agregar(todas);
  consultar.agregar(new OpcionSalir("Volver"));
  
  principal.agregar(insertarEfemeride);
  principal.agregar(eliminarEfemeride);
  principal.agregar(actualizarEfemeride);
  principal.agregar(consultar);
  principal.agregar(new OpcionSalir("Salir"));
  
  principal.ejecutar();
  
  BaseDatos.desconectar();

 }

 protected static void onInsertarEfemeride() {

  Efemeride efemeride = new Efemeride();
  
  String texto = Entrada.leerCadena("Introduzca el texto de la efeméride");
  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm/aaaa)");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

  efemeride.setTexto(texto);
  efemeride.setFecha(fecha.getTime());
  
  try {
   efemerides.insertar(efemeride);
   System.out.println("**EFEMÉRIDE INSERTADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEliminarEfemeride() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a eliminar");
  
  try {
   efemerides.eliminar(id);
   System.out.println("**EFEMÉRIDE ELIMINADA**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }

 protected static void onActualizarEfemeride() {

  Efemeride efemeride = new Efemeride();
  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a actualizar");
  try {
   Efemeride recuperada = efemerides.recuperar(id);
   System.out.println("Datos de la efeméride a actualizar:");
   System.out.println("Id: "+id+" - Texto: "+recuperada.getTexto()+" - Fecha: "+DateUtils.formatear(recuperada.getFecha()));
   
   String texto = Entrada.leerCadena("Introduzca el nuevo texto de la efeméride");
   String fechaTexto = Entrada.leerCadena("Introduzca la nueva fecha (dd/mm/aaaa)");
   
   String[] partes = fechaTexto.split("/");
   GregorianCalendar fecha = new GregorianCalendar(Integer.parseInt(partes[2]), (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));

   efemeride.setId(id);
   efemeride.setTexto(texto);
   efemeride.setFecha(fecha.getTime());
   
   efemerides.actualizar(efemeride);
   System.out.println("**EFEMÉRIDE ACTUALIZADA CON ÉXITO**");
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorId() {

  Integer id = Entrada.leerEntero("Introduzca el identificador de la efeméride a buscar");
  try {
   Efemeride efemeride = efemerides.recuperar(id);
   System.out.println("DATOS DE LA EFEMÉRIDE:");
   System.out.println("Id: "+id+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onBuscarPorFecha() {

  String fechaTexto = Entrada.leerCadena("Introduzca la fecha (dd/mm) de las efemérides a buscar");
  String[] partes = fechaTexto.split("/");
  
  GregorianCalendar fecha = new GregorianCalendar(1999, (Integer.parseInt(partes[1])-1), Integer.parseInt(partes[0]));
  
  try {
   List <Efemeride> listado = efemerides.recuperarPorFecha(fecha.getTime());
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA ESPECIFICADO**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
   
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
  
 }
 
 protected static void onEfemeridesHoy() {
  
  try {
   List <Efemeride> listado = efemerides.hoy();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES PARA EL DÍA DE HOY**");
   }
   else {
    System.out.println("LISTADO DE LAS EFEMÉRIDES DE HOY:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }
 }
 
 protected static void onTodas() {
  try {
   List <Efemeride> listado = efemerides.recuperarTodas();
   if (listado.isEmpty()) {
    System.out.println("**NO HAY EFEMÉRIDES ALMACENADAS**");
   }
   else {
    System.out.println("LISTADO DE TODAS LAS EFEMÉRIDES:");
    for (Efemeride efemeride : listado) {
     System.out.println("Id: "+efemeride.getId()+" - Texto: "+efemeride.getTexto()+" - Fecha: "+DateUtils.formatear(efemeride.getFecha()));
    }
   }
   Entrada.pausa();
  } catch (EfemerideException e) {
   System.err.println(e.getMessage());
   Entrada.pausa();
  }  
 }

}

También se creó una clase con utilidades para trabajar con las fechas, debido a que nos veíamos en la obligación de utilizar por una parte la clase java.util.Date y por otra java.sql.Date. Esta clase, como la clase "BaseDatos", se puede reutilizar cada vez que tengamos que trabajar con fechas en el acceso a bases de datos.

CLASE DATEUTILS

public class DateUtils {
 
 public static java.util.Date crearFecha(int dia, int mes, int anyo) {
  GregorianCalendar calendario = new GregorianCalendar(anyo, mes-1, dia);
  return calendario.getTime();
 }
 
 public static java.sql.Date convertir(java.util.Date fecha) {
  return new java.sql.Date(fecha.getTime());
 }
 
 public static int dia(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.DAY_OF_MONTH);
 }
 
 public static int mes(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.MONTH)+1;
 }
 
 public static int anyo(java.util.Date fecha) {
  GregorianCalendar calendario = new GregorianCalendar();
  calendario.setTime(fecha);
  
  return calendario.get(Calendar.YEAR);
 }
 
 public static String formatear(java.util.Date fecha) {
  SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
  return formatter.format(fecha);
 }

}

lunes, 31 de octubre de 2011

Clase "BaseDatos" y fichero de configuración

Hace algunos días comencé con el acceso a bases de datos desde Java y expliqué, brevemente, los pasos a seguir para implementar el puente JDBC-ODBC. Siguiendo con el tema de bases de datos, os dejo en esta entrada la clase "BaseDatos" y el fichero de configuración para el acceso a las bases de datos.

Cada proyecto nuevo en el que queramos acceder a una base de datos debe llevar tanto esta clase, como su correspondiente fichero de configuración, con los datos correspondientes.

La clase "BaseDatos" nos permitirá realizar todas las gestiones necesarias para acceder a una base de datos:
  • Registrar el driver.
  • Conectar a la base de datos.
  • Cerrar la conexión con la base de datos.
Al implementar esta clase, haremos que sólo se cree una conexión, que se utilizará para todos los accesos que se realicen a la base de datos en cada conexión. De esta manera no se tendrá que abrir y cerrar la conexión cada vez que se quiera acceder a la base de datos. Para conseguirlo el constructor de la clase es privado (no se podrá instanciar) y la conexión propiamente dicha será un atributo estático.

CLASE "BASEDATOS"

public class BaseDatos {
 
 private static Connection conexion = null;
 // Para utilizar el fichero de propiedades:
 private static ResourceBundle bundle = ResourceBundle.getBundle("dir.efemerides.config");
 
 // De esta manera no podemos instanciar BaseDatos
 private BaseDatos() {
 }
 
 public static Connection getConnection() throws SQLException {
  if (conexion == null || conexion.isClosed()) {
   conexion = conectar();
  }
  return conexion;
 }

 private static Connection conectar() {
  registrarDriver();
  Connection conexion = null;
  try {
   String url = bundle.getString("db.url");
   String username = bundle.getString("db.username");
   String password = bundle.getString("db.password");
   conexion = DriverManager.getConnection(url, username, password);
  } catch (SQLException e) {
   System.err.println("No fue posible establecer la conexión.");
   e.printStackTrace();
  }
  
  return conexion;
 }
 
 public static void desconectar() {
  try {
   if (conexion != null && !conexion.isClosed()) {
    conexion.close();
    conexion = null;
   }
  } catch (SQLException e) {
   System.err.println("No fue posible cerrar la conexión.");
   e.printStackTrace();
  }
 }
 
 private static void registrarDriver() {
  try {
   Class.forName(bundle.getString("db.driver"));
  } catch (ClassNotFoundException e) {
   System.err.println("Error al cargar el driver JDBC");
   e.printStackTrace();
  }
 }
}

El fichero de configuración tendrá los datos necesarios para acceder a la base de datos. Estos datos serán los que hayamos especificado al implementar el puente JDBC-ODBC.

La URL de conexión corresponde al nombre que le hayamos dado al origen de datos.

FICHERO DE CONFIGURACIÓN

# Driver de la base de datos:
db.driver=sun.jdbc.odbc.JdbcOdbcDriver

# Url de conexión:
db.url=jdbc:odbc:Efemerides

# Usuario y contraseña:
db.username=admin
db.password=1234

miércoles, 19 de octubre de 2011

Acceso a bases de datos Access - Puente JDBC-ODBC

Este curso hemos seguido con Java. El primer tema que hemos estado trabajando es el acceso a bases de datos utilizando este lenguaje. Inicialmente trabajaremos con MS Access, por lo que tenemos que implementar el puente JDBC-ODBC antes de empezar a trabajar con Java.

A continuación explico brevemente los pasos a seguir:

**Una vez creada la base de datos en MS Access, vamos al Panel de control.

**Elegimos "Herramientas administrativas".


**Doble clic en "Orígenes de datos ODBC".


**El origen de datos lo podemos crear en las pestañas "DSN de usuario" o "DSN de sistema", si queremos que esté disponible sólo para nosotros o para cualquier usuario del equipo.
**Hacemos clic en "Agregar...".


**Elegimos el driver. En este caso el de Microsoft Access y hacemos clic en "Finalizar".


**Se abre un cuadro como el siguiente. Indicamos el nombre que queremos dar al origen de datos y, si queremos, una pequeña descripción.


**Hacemos clic en "Seleccionar", para elegir la base de datos.


**La seleccionamos y hacemos clic en "Aceptar".


**Hacemos clic en "Avanzadas...".


**Especificamos el nombre de inicio de sesión y la contraseña.


**En el panel "Opciones", elegimos "Driver" y le damos como valor el mismo que hemos puesto como nombre del origen de datos. Hacemos clic en "Aceptar".


**Ya hemos creado el origen de datos para la base de datos creada previamente. Lo comprobamos en el listado.


Hay que tener en cuenta que se debe crear un origen de datos por cada base de datos que creemos. Si movemos esta base de datos a otro ordenador, también debemos crear de nuevo el origen de datos en ese equipo.
Espero que se entienda y sea útil.