Autor Tema: intervalos de fechas MySql con Java para comprobar reservas en hotel  (Leído 29799 veces)

dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #20 en: 25 de Agosto 2014, 22:56 »
A ver si te vale esto para exportarla y nos la pasas con los datos, ejk lo suyo es que tengan datos dentro.

http://www.alvarolara.com/2013/02/25/backup-de-base-de-datos-desde-mysql-workbench/

Otra cosa la forma mas fácil de rellenar un jtable es con su constructor
JTable(Object[][] rowData, Object[] columnNames);

Este constructor recibe un array de dos dimensiones con los datos, y otro array de na dimensión con los títulos de las columnas y bueno eso, lo que te comento, si nos pudieras pasar el script sql con los datos seria estupendo...


gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #21 en: 25 de Agosto 2014, 23:29 »
Hola Dongo, para rellenar el JTablo yo lo hago asi;

Código: [Seleccionar]
public DefaultTableModel mostrar (String buscar){
    DefaultTableModel modelob;
    //Podemos usar el metodo varias veces con like %variable%
    String sql = "Select * from habitacion where idhabitacion like '%"+buscar+"%' order by idhabitacion";
    System.out.println("El sql en mostrar es; " + sql);
    String [] titulos = {"ID", "Número", "Piso", "Descripción", "Carácteristicas", "Precio diario", "Estado", "Tipo de habitación"};
    String [] registro = new String [8];
    modelob = new DefaultTableModel(null, titulos);
   
   
    try {
       
        conn.conecta();
        conn.crearSentencia();
        conn.ejecutaSQL(sql);
       
        while (conn.getRs().next()){
            registro [0]= conn.getRs().getString("idhabitacion");
            registro[1] = conn.getRs().getString("numero");
            registro[2] = conn.getRs().getString("piso");
            registro[3] = conn.getRs().getString("descripcion");
            registro[4] = conn.getRs().getString("caracteristicas");
            registro[5] = conn.getRs().getString("precio_diario");
            registro [6] = conn.getRs().getString("estado");
            registro [7] = conn.getRs().getString("tipo_habitacion");
           
            totalRegistro = totalRegistro + 1;
            modelob.addRow(registro);
           
           
        }
       conn.cerrarConexion();
   
       
    } catch (SQLException e) {
        JOptionPane.showMessageDialog(null, "No se ha podido recuperar el dato.");
    }
               
        return modelob;
}
   



Te subo la BBDD con 6 habitaciones  y 8 reservas.

dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #22 en: 26 de Agosto 2014, 10:57 »
Mira aquí tienes un método, al que le pasas una fecha de inicio, una fecha fin en formatos "d-m-y" y te devuelve una sentencia que al ejecutarla te devolverá las habitaciones libres en ese periodo:

Código: [Seleccionar]
public static String creaHabitacionesLibresQuery(String fecha_inicio, String fecha_fin) {
        String cadena = "select * from habitacion where estado='Disponible'  and idhabitacion\n"
                + "not in(select idhabitacion from reserva\n"
                + "where"
                + "( STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')  between fecha_reserva and  fecha_salida )\n"
                + "or\n"
                + "( STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')  between fecha_reserva and fecha_salida)\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')<fecha_reserva)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')> fecha_reserva))\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')>fecha_salida)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')< fecha_salida)))\n";

        return cadena;
    }


La forma de usarlo seria:

Código: [Seleccionar]
public static void main(String[] arg){
     String consulta = HabitacionesDisponibles.creaHabitacionesLibresQuery("01-01-2014", "25-01-2014");//esto es así porke yo he llamado HabitacionesDisponibles a la clase ke contiene este metodo
     System.out.println(consulta);
}



Lo único que faltaría sería coger esa cadena generada por ese método y ejecutarla con un statment, después simplemente rellenas la tabla con los datos devueltos por esta consulta...

Ahora si me aburro durante la mañana, te haré una clase de ejemplo de como yo relleno una tabla, y como dividir la funcionalidad en distintos métodos para que no este todo dentro de un mismo método.

Un saludo!

Nota:Yo he probado distintas sentencias y me ha devuelto siempre las habitaciones libres, si detectas que da error en algún caso, comentanoslo.
« Última modificación: 26 de Agosto 2014, 11:06 por dongo »

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #23 en: 26 de Agosto 2014, 13:57 »
Hola Dogo, gracias por el interes que estas mostrando, te lo agradezco. He visto el método con la select y parece que va funcionar, pero mi poblema es que no se que hacer con ese Array de habitaciones disponibles.

Vamos para que quede claro, si me devuelve 2id de habitaciones libres 1,5,20, 30" no se luego como hacer para seleccionar esas id de la tabla habitaciones. "Hay que pensar que esas id van a ir cambiando, son dinamicas". Ese era mi problema de un principio más que el saber que habitaciones eran las que estaban libres.

Mira te pongo la clase como la tengo yo, al final esta el método que debe devolver el modelo con Table de las habitaciones disponibles;

Código: [Seleccionar]

mport Datos.Habitacion;
import Datos.Reservas;
import Presentacion.frmEscritorio;
import java.awt.HeadlessException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

/**
 *
 * @author carlos
 */
public class LReservas {

    Conexion conn = new Conexion();
    Reservas obj;
    public int totalRegistro = 0;

    /**
     * Metodo para buscar en el table model
     *
     * @param buscar Recibe un String para ser ejecutado en el MySql
     * @return Devuelve un TableModel
     */
    public DefaultTableModel mostrar(String buscar) {
       
        String sql="";
       
       
        DefaultTableModel modelob;
       
        //Podemos usar el metodo varias veces con like %variable%
        sql = "Select r.idreserva,r.idhabitacion,h.numero,r.idcliente," +
                "(select nombre from persona where idpersona=r.idcliente) as Ncliente," +
                "(select apaterno from persona where idpersona=r.idcliente) as Acliente," +
                "r.idtrabajador, (select nombre from persona where idpersona =r.idtrabajador)as Ntrabajador," +
                "(select apaterno from persona where idpersona=r.idtrabajador) as Atrabajador," +
                "r.tipo_reserva, r.fecha_reserva,r.fecha_ingreso,r.fecha_salida,"+
                "r.costo_alojamiento,r.observacion, r.estado from reserva r inner join habitacion h on h.idhabitacion=r.idhabitacion" +
                " where r.idreserva like '%"+buscar+"%'  order by r.idreserva desc";
           
        System.out.println("El sql en mostrar en Reservas vale ===>>>" + sql);
       
       
        String[] titulos = {"ID", "Id Habitación", "Número", "Id Cliente", "Cliente", "Id Trabajador", "Trabajador", "Tipo Reserva", "Fecha Reserva", "Fecha Ingreso", "Fecha Salida", "Total", "Observaciones", "Estado" };
        String[] registro = new String [14];
          modelob = new DefaultTableModel(null, titulos);
         
        try{
           
        conn.conecta();
        conn.crearSentencia();
        conn.ejecutaSQL(sql);
            while (conn.getRs().next()) {
                registro[0] = conn.getRs().getString("idreserva");
                registro[1] = conn.getRs().getString("idhabitacion");
                registro[2] = conn.getRs().getString("numero");
                registro[3] = conn.getRs().getString("idcliente");
                registro[4] = conn.getRs().getString("Ncliente")+ " " + conn.getRs().getString("Acliente");
                registro[5] = conn.getRs().getString("idtrabajador");
                registro[6] = conn.getRs().getString("Ntrabajador") + " " + conn.getRs().getString("Atrabajador");
                registro[7] = conn.getRs().getString("tipo_reserva");
                registro[8] = conn.getRs().getString("fecha_reserva");
                registro[9] = conn.getRs().getString("fecha_ingreso");
                registro[10] = conn.getRs().getString("fecha_salida");
                registro[11] = conn.getRs().getString("costo_alojamiento");
                registro[12] = conn.getRs().getString("observacion");
                registro[13] = conn.getRs().getString("estado");

             totalRegistro = totalRegistro + 1;
                System.out.println("el total registros es " +totalRegistro);
                modelob.addRow(registro);

            }
            conn.cerrarConexion();

        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "No se ha podido recuperar los datos desde mostrar." + e);
        }
       
       
       
       
        return modelob;
    }

    /**
     * Funcion insertar habitacion en la bbdd.
     *
     * @param obj recive un objeto de habitacion
     * @return devuelve el número de filas al realizar la operación
     *
     */
    public int insertar(Reservas obj) {

        //SQL para persona
        String sql = "insert into reserva (idhabitacion,idcliente, idtrabajador,tipo_reserva, fecha_reserva, fecha_ingreso, fecha_salida, costo_alojamiento, observacion, estado)"
                + " values ("+ obj.getIdhabitacion() + "," + obj.getIdcliente() + "," + obj.getIdtrabajador() + ",'" + obj.getTipoReserva() + "','" + obj.getfReserva() + "','" + obj.getfIngreso() + "','"
                + obj.getfSalida() + "'," + obj.getTotal() + ",'" + obj.getObservacion() + "','" + obj.getEstado()+ "' )";
        System.out.println("La sql insertar en RESERVAS vale => " +sql);
       
        int resultado = -1;
       
        try {

            conn.conecta();
            conn.crearSentencia();
            resultado = conn.updateSQL(sql); //Intentamos ingresar a la persona

            if (resultado >= 0) {

                JOptionPane.showMessageDialog(null, "La reserva ha sido ingresada con exicto.");
               
            } else {
                JOptionPane.showMessageDialog(null, "La reserva no se ha ha podido ser ingresada.");
            }
            conn.cerrarConexion();
        } catch (HeadlessException | SQLException e) {
            JOptionPane.showMessageDialog(null, "Error: " + e);
        }

        return resultado;
    }

    /**
     * Metodo para actualizar la bbdd
     *
     * @return Un entero para saber el numero de filas afectadas
     * @param obj Recibe objeto de habitacion
     */
    public int actualizar(Reservas obj) {

        String sql = "Update reserva set idhabitacion=" + obj.getIdhabitacion() + ",idcliente=" + obj.getIdcliente() + ",idtrabajador=" + obj.getIdtrabajador() + ",tipo_reserva='"
                + obj.getTipoReserva() + "', fecha_reserva='" + obj.getfReserva() + "',fecha_ingreso='" + obj.getfIngreso() + "',fecha_salida='"
                + obj.getfSalida() + "',costo_alojamiento=" + obj.getTotal() + ",observacion='"+obj.getObservacion()+"',estado='"+obj.getEstado()+"' where idreserva=" + obj.getIdreserva() + "";

       

        int resultado = -1;
       

        System.out.println("sql actualizar una RESERVA=> " + sql);
       

        try {

            conn.conecta();
            conn.crearSentencia();
            resultado = conn.updateSQL(sql);

            if (resultado >= 0) {

                JOptionPane.showMessageDialog(null, "La reserva se ha actualizado correctament.");
            } else {
                JOptionPane.showMessageDialog(null, "La reserva  no ha podido ser actualiza.");
            }
            conn.cerrarConexion();

        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "El error al actualizar ha sido, " + e);
        }

        return resultado;

    }

    /**
     * Metodo para eliminar habitaciones de la bbdd
     *
     * @param id Recibe el id de la habitación para ser eliminada
     * @return Devuelve el número de filas afectadas
     */
    public int eliminar(int id) {

        String sqlT = "Delete from reserva where idreserva =" + id + "";
       

        System.out.println("sql al eliminar Reserva => " + sqlT);
       

        int resultado = -1;
     

        try {

            conn.conecta();
            conn.crearSentencia();
            resultado = conn.updateSQL(sqlT);

            if (resultado >= 0) {

                JOptionPane.showMessageDialog(null, "La reserva ha sido eliminadoa correctamente.");

            } else {
                JOptionPane.showMessageDialog(null, "No hemos podido eliminar el la reserva.");
            }

            conn.cerrarConexion();

        } catch (SQLException e) {

            JOptionPane.showMessageDialog(null, "Hemos tenido un problema al eliminar la habitación, " + e);
        }

        return resultado;
    }

   
 /**
     * Metodo para buscar en el table model
     *las habitaciones disponibles en las fechas indicadas
     * @param fechaInicio
     * @param fechaSalida
     * @param buscar Recibe un String para ser ejecutado en el MySql
     * @return Devuelve un TableModel
     */
    public DefaultTableModel mostrarHabitacionesLibres(String fechaInicio, String fechaSalida) {
       
        String sql="";   
        // SQL saber habitaciones ocupadas
        sql ="Select ha.idhabitacion from reserva re, habitacion ha " +"\n" +
        " where ha.idhabitacion=re.idhabitacion and  '"+fechaInicio+"'  >= re.fecha_ingreso \n" +
        "and '"+fechaInicio+"' <= re.fecha_salida and ha.estado='Disponible' ";       
       
       
        DefaultTableModel modelob = null;
        String[] titulos = {"ID",  "Numero", "Piso", "Descripcion", "Caracteristicas", "Precio Diario", "Estado", "Tipo de Habitacion"};
        String[] registro = new String [8];
       
        modelob = new DefaultTableModel(null,titulos);
        try{
           
       
        conn.conecta();
        conn.crearSentencia();
        conn.ejecutaSQL(sql); //Sentencia para saber el tamaño, total de habitaciones que tenemos
        while (conn.getRs().next()){
           
        }
        conn.cerrarConexion();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "No se ha podido recuperar los datos desde mostrarHabitacionesLibres." + e);
        }
 
           return modelob;
    }   
                   

///clase   

}


Como comento, mi problema es que aunque consiga el array con las habitaciones libres no se como manejarlo.


dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #24 en: 26 de Agosto 2014, 14:45 »
Entonces tu problema creo que es la forma en la que intentas crear el JTable.

Haber la clase DefaultTableModel es una clase abstracta, lo que significa que esta diseñada para ser extendida. Esto se hace mayormente cuando se le quiere dar un aspecto diferente a cada fila o columna o se quiere añadir un listener a una celda,..., por ejemplo imagina que quieres obtener un listado de todas las habitaciones y crear una tabla en que las disponibles salen con letra verde, y las ocupadas en rojo.

En este caso si seria adecuado crear una clase que extienda de DefaultTableModel e implementar esta funcionalidad, osea tendrías que ir fila por fila y dependiendo de si esta ocupada o libre pintarla de un color.

Ahora si lo que quieres es crear una tabla sin mas, solo con datos, la forma mas sencilla es como ya te dije, con el constructor:

Código: [Seleccionar]
JTable(Object[][] rowData, Object[] columnNames);

Con este constructor no nos es necesario andar yendo fila por fila rellenando la tabla sino que las filas se rellenan automáticamente.

Te adjunto un ejemplo con lo mínimo para poder crear un jtable:

Fichero CreaTabla.java:
Código: [Seleccionar]

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;


public class CreaTabla extends JFrame {


    public CreaTabla(String titulo) {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//finaliza el programa cuando se da click en la X
        this.setSize(640, 480);//configurando tamaño de la ventana
        this.setLocationRelativeTo(null);
        this.setVisible(true);//configurando visualización de la ventana

    }
    public static void main(String[] arg) {
        CreaTabla cr = new CreaTabla("habitaciones");
        //creo el array de datos para la tabla
        String[][] datos = {{"1", "Disponible", "doble"}, {"2", "Disponible", "Simple"}, {"3", "No disponible", "Simple"},
        {"4", "Disponible", "Simple"}, {"5", "Disponible", "Simple"}, {"6", "Disponible", "Simple"}, {"7", "Disponible", "Simple"},
        {"8", "Disponible", "Simple"}, {"9", "Disponible", "Simple"}, {"10", "Disponible", "Simple"}};
        //creo el array con los nombres de las columnas
        String[] nombresColumnas = {"id_habitacion", "estado", "tipo"};
        //creo el jtable con el array de datos y el array de nombrs columnas
        JTable tabla=new JTable(datos,nombresColumnas);
        //creo un jscrollpane  y le paso como parametro del constructor la tabla
        //esto ahi ke hacerlo asi para ke salgan los titulos de las columnas y barra de scroll derecha
        JScrollPane panel_temp =new JScrollPane(tabla);
        //añado el Jscroll al contenedor del JFrame
        cr.add(panel_temp);
        //hago el JFrame visible
        cr.setVisible(true);
       
    }
}
« Última modificación: 26 de Agosto 2014, 14:54 por dongo »

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #25 en: 26 de Agosto 2014, 14:54 »
Holo Dogo, tú olvidate del JTable. Mira yo puedo hacer esto;

Select numero_habitacion,estado,color  from habitacion where idhabitacion= 5, and idhabitacion=10 etc,etc

Es sencillo. Bien, tú ahora tienes una variable que es un Array con id de habitaciones, que es lo que tú has conseguido en el método.

¿Como haces la select, utilizando las variables que hay en el Array?

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #26 en: 26 de Agosto 2014, 15:04 »
A mi lo mas sencillo que se me ha ocurrido es crear una reserva para cada habitacion = null
todos los campos en la tabla reserva, de esa forma puedo hacer;

select idhabitacion,numero,piso,descripcion,caracteristicas,precio_diario,estado,tipo_habitacion
from habitacion ha, reserva re where ha.idhabitacion=re.idhabitacion and fecha-entrada
+ todas las posiblidades.  :o


Es la unica forma que veo que puedo hacerlo, pero para ello como comento tengo que hacer una reserva inicial de toddas las habitaciones en la tabla reserrvas,dejandolo todo a null para poder comparar las fechas, con las reservas que si "son autenticas".

No me parece elegante la verdad, pero bueno.   :-\

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #27 en: 26 de Agosto 2014, 15:34 »
Una prueba rápida que he hecho y parece funcionar bien, "OJO, he hecho una reserva para todas y cada una de las habitaciones con null en todos los campos" ;


Código: [Seleccionar]

 public DefaultTableModel mostrarHabitacionesLibres(String fechaInicio, String fechaSalida) {
       
        String sql="";
   
        // SQL saber habitaciones libres
        sql ="Select distinct ha.idhabitacion,numero,piso,descripcion,caracteristicas,precio_diario,ha.estado,tipo_habitacion  "
                + " from reserva re, habitacion ha " +"\n" +
        " where ha.idhabitacion=re.idhabitacion and  '"+fechaInicio+"' < re.fecha_ingreso \n" +
        "and '"+fechaSalida+"' < re.fecha_ingreso or '"+fechaInicio+"' > fecha_salida and "
        + "ha.estado='Disponible' ";       
        System.out.println("La sql habitaciones libres vale=>" + sql);
       
        DefaultTableModel modelob = null;
        String[] titulos = {"ID",  "Numero", "Piso", "Descripcion", "Caracteristicas", "Precio Diario", "Estado", "Tipo de Habitacion"};
        String[] registro = new String [8];
       
        modelob = new DefaultTableModel(null,titulos);
        try{
           
       
        conn.conecta();
        conn.crearSentencia();
        conn.ejecutaSQL(sql);
        while (conn.getRs().next()){
           
                registro[0] = conn.getRs().getString("idhabitacion");
                registro[1] = conn.getRs().getString("numero");
                registro[2] = conn.getRs().getString("piso");
                registro[3] = conn.getRs().getString("descripcion");
                registro[4] = conn.getRs().getString("caracteristicas");
                registro[5] = conn.getRs().getString("precio_diario");
                registro[6] = conn.getRs().getString("estado");
                registro[7] = conn.getRs().getString("tipo_habitacion");
               
                totalRegistro = totalRegistro + 1;
                System.out.println("el total registros es " +totalRegistro);
                modelob.addRow(registro);
        }
        conn.cerrarConexion();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "No se ha podido recuperar los datos desde mostrarHabitacionesLibres." + e);
        }
 
           return modelob;
    }   
                   




dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #28 en: 26 de Agosto 2014, 16:02 »
Pues si te funciona estupendo, pero como tu dices, no es la forma mas elegante de hacerlo teniendo que meter esas id a null en la tabla reservas....

Por eso te vuelvo a pegar el código del método que te genera la select...

Código: [Seleccionar]
public static String creaHabitacionesLibresQuery(String fecha_inicio, String fecha_fin) {
        String cadena = "select idhabitacion, numero,piso,descripcion,caracteristicas,precio_diario,estado,tipo_habitacion\n "
                + "from habitacion where estado='Disponible'  and idhabitacion\n"
                + "not in(select idhabitacion from reserva\n"
                + "where"
                + "( STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')  between fecha_reserva and  fecha_salida )\n"
                + "or\n"
                + "( STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')  between fecha_reserva and fecha_salida)\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')<fecha_reserva)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')> fecha_reserva))\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')>fecha_salida)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')< fecha_salida)))\n";

        return cadena;
    }


si ejecutas este método con fecha_inicio("01-01-2014") y fecha_fin("25-01-2014") te devolverá esta cadena de texto:

Código: [Seleccionar]
select idhabitacion, numero,piso, descripcion, caracteristicas, precio_diario, estado, tipo_habitacion
 from habitacion where estado='Disponible'  and idhabitacion
not in(select idhabitacion from reserva
where( STR_TO_DATE('01-01-2014', '%d-%m-%Y')  between fecha_reserva and  fecha_salida )
or
( STR_TO_DATE('25-01-2014', '%d-%m-%Y')  between fecha_reserva and fecha_salida)
or
((STR_TO_DATE('01-01-2014', '%d-%m-%Y')<fecha_reserva)
and
(STR_TO_DATE('25-01-2014', '%d-%m-%Y')> fecha_reserva))
or
((STR_TO_DATE('25-01-2014', '%d-%m-%Y')>fecha_salida)
and
(STR_TO_DATE('01-01-2014', '%d-%m-%Y')< fecha_salida)))

Si ejecutas esa consulta en mysql workbench te darás cuenta que ahí ya tienes todos los datos de las habitaciones disponibles, y no te hace falta tener filas a null ni cosas raras...

Ya no se si tu duda es esta, o el código del DefaultTableModel, si es como rellenar un array con los datos de un resultSet, o que, en cada post te entiendo una cosa diferente...XD

Pero no te preocupes a veces es difícil entender lo que se quiere hacer...

Nada tio si ya te funciona pos nada, estupendo a seguir palante ;)

Un saludo!!

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #29 en: 26 de Agosto 2014, 16:41 »
Vale Dongo, he probado lo que me has pasado y parece que funciona. Yo pensaba que una subconsulta solo podía devolver un valor, solo un unico valor de una unica fila y columna. Vamos un valor escalar.

Tu has hecho una subconsulta que te devuelve varios valores. A mi muchas veces me devuelve el siguiente error:

SQL Error: Subquery returns more than 1 row

A ver por eso todo el lio que yo comenteba/hacia de crear un array con las habitaciones que estaban ocupadas en Reservas, y luego como he comentado no sabia que hacer con esas id, y intentaba hacer un bucle.

dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #30 en: 26 de Agosto 2014, 17:40 »
Bueno, yo empezaría por añadir estos métodos a tu clase Conexión.

El primero recibe un String con una consulta y un objeto de tipo conexion y devuelve un array bidimensional con todos los datos de la consulta, ya tenga 1 fila o tenga 1 millon.

El segundo, recibe un String con una consulta y un objeto de tipo conexion y devuelve un array unidimensional con el nombre de las columnas de esa consulta.

Método 1:
Código: [Seleccionar]
//metodo ke recibe una cadena de texto con una consulta, un objeto de tipo Conection y
    //devuelve un array con los datos( metodo generico para cualquier consulta )
    /*Nota: Este metodo deberia estar en una clase aparte llamada por ejemplo JDBCUtil*/

    public static String[][] ejecutaConsulta(String consulta, Connection p_Conexion) {
        //creamo el array vacio ke contendrá los datos
        String[][] datos = null;

        //creamos un objeto statement vacio
        Statement st = null;
        try {
            //inicio el objeto statement ke me permitira obtener un resultSet recorrible en ambos sentidos y de solo lectura
            st = p_Conexion.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            //creo el resultset y ejecuto la consulta pasada por parametro a traves del objeto statement
            ResultSet rs = st.executeQuery(consulta);
            //Obtengo un resultSet con los metadatos de la consulta(num columnas, nom columnas, ....)
            ResultSetMetaData rsm = rs.getMetaData();
           
            //obtengo el numero de columnas del resultsetmetadata y lo guardo en la variable ke cree para ello
            int numCol = rsm.getColumnCount();
            //me voy a la ultima fila del resultSet
            rs.last();
            //creo una variable y el asigno el valor de la fila actual, en este caso la ultima.
            int numFilas = rs.getRow();
            //vuelvo al principio del resultset para empezar a recorrerlo
            rs.beforeFirst();
            //inicializo el array de datos con el numero de filas y el numero de columnas
            datos = new String[numFilas][numCol];
            //creo un contador
            int i = 0;
            //recorro el resultSet columna a columna y fila a fila y guardo el dato en el array
            while (rs.next()) {
                for (int j = 0; j < datos[0].length; j++) {
                    datos[i][j] = rs.getString(j + 1);
                }
                i++;
            }
        } catch (SQLException e) {
            //error si la consulta falla
            System.out.println("Error al ejecutar la consulta " + e.getMessage());
        }
        //Cierro el objeto statement.
        try {
            if (st != null) {
                st.close();
            }
        } catch (SQLException ex) {
            //error si el statment no se puede cerrar...
            System.out.println("Error cerrando el resultset " + ex.getMessage());
        }
        //devuelvo los datos
        return datos;

    }

Método 2:
Código: [Seleccionar]
//metodo ke recibe una cadena con una consulta, un objeto de tipo Conection y
    //devuelve los nombres de las columnas de esa consulta (metodo generico para cualkier consulta)
    //este metodo viene hacer lo mismo ke el anterior pero obtengo el nombre de las columnas
    //del objeto ResultSetMeataData
    /*Nota: Este metodo deberia estar en una clase aparte llamada por ejemplo JDBCUtil*/

public static String[] getNombresColumnas(String consulta, Connection p_Conexion) {
        String[] nombresColumnas = null;

        Statement st = null;
        try {
            st = p_Conexion.createStatement();

            ResultSet rs = st.executeQuery(consulta);
            ResultSetMetaData rsm = rs.getMetaData();
            nombresColumnas = new String[rsm.getColumnCount()];

            for (int i = 0; i < rsm.getColumnCount(); i++) {
                nombresColumnas[i] = rsm.getColumnLabel(i + 1);
            }
        } catch (SQLException e) {
            System.out.println("Error obteniendo nombres de las columnas " + e.getMessage());
        }
        try {
            if (st != null) {
                st.close();
            }
        } catch (SQLException ex) {
            System.out.println("Error cerrando el resultset " + ex.getMessage());
        }
        return nombresColumnas;
    }

Bien, lo siguiente que haría, sería crear un método que me genere la cadena de texto con la consulta, que es el método que te pase antes:

Código: [Seleccionar]
public static String creaHabitacionesLibresQuery(String fecha_inicio, String fecha_fin) {
        String cadena = "select idhabitacion, numero,piso,descripcion,caracteristicas,precio_diario,estado,tipo_habitacion\n "
                + "from habitacion where estado='Disponible'  and idhabitacion\n"
                + "not in(select idhabitacion from reserva\n"
                + "where"
                + "( STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')  between fecha_reserva and  fecha_salida )\n"
                + "or\n"
                + "( STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')  between fecha_reserva and fecha_salida)\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')<fecha_reserva)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')> fecha_reserva))\n"
                + "or\n"
                + "((STR_TO_DATE('" + fecha_fin + "', '%d-%m-%Y')>fecha_salida)\n"
                + "and\n"
                + "(STR_TO_DATE('" + fecha_inicio + "', '%d-%m-%Y')< fecha_salida)))\n";

        return cadena;
    }

Bien, una vez te tengo los métodos para obtener los datos de una consulta, obtener los nombres de las columnas de una consulta y obtener la sentencia sql que quiero ejecutar, simplemente crearíamos el método
que crea el modelo y que contendría el siguiente código.

Código: [Seleccionar]
public DefaultTableModel mostrarHabitacionesLibres(String fechaInicio, String fechaSalida) {
Connection conn;
/*aki debemos iniciar el objeto conn con una conexion a tu base de datos*/
//Una vez el conn esta iniciado solo deberemos hacer:
String consulta= NombreClase.creaHabitacionesLibresQuery(fechaInicio,fechaSalida);
String[] nombresColumnas= NombreClase.getNombresColumnas(consulta, conn);
String[][] datos= NombreClase.ejecutaConsulta(consulta, conn);
DefaultTableModel modelo=new DefaultTableModel(datos, nombresColumnas);

return modelo;
}


Fíjate ke debes crear un objeto conection y después ir llamando a los métodos creados anteriormente
al ser estáticos, Yo he puesto NombreClase, esto debes cambiarlo por el nombre de la clase donde crees estos métodos.

Te recomiendo eches un ojo a los dos primeros métodos, ya que son métodos genéricos para ejecutar una consulta cualquiera y obtener un array con los datos ...

Y bueno, esta es la forma "mas sencilla" en que yo haría para crear un modelo para un jtable con una consulta.

Y nada un saludo!!

gatoher

  • Principiante
  • **
  • APR2.COM
  • Mensajes: 86
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #31 en: 27 de Agosto 2014, 15:31 »
Hola Dogo, ayer ya no puede responderte, estaba liado haciendo cosas en casa  >:(
Bueno he visto como haces para llenar el Table, te pogo como lo tengo yo:

Clase Conexion"para todo el proyecto":

Código: [Seleccionar]
/**
     * Metodo para conectarnos a la base de datos
     * @throws java.sql.SQLException
     */
   
    public void conecta () throws SQLException{
     
       
        try {
        //Registramos el driver
        String driver="com.mysql.jdbc.Driver";
        //Class.forName metodo de la clase DriverManager
        Class.forName(driver).newInstance();
         //Abrimos la conexion con la base de datos
        System.out.println("Conectando con la base de datos");
        String jdbcUrl = "jdbc:mysql://localhost:3306/reservas";
        //objeto de tipo connection, hay varios metodos getConnection
         //creamos una conexion con la base de datos
         conn = DriverManager.getConnection(jdbcUrl,"root","");
         System.out.println("Conexión establecida con la Base de datos...");
       
        }catch( SQLException error){
            Throwable fillInStackTrace = error.fillInStackTrace();
            JOptionPane.showMessageDialog(null, "Error al intentar conectar con la base de datos."+ fillInStackTrace);
        } catch (Exception error){
            JOptionPane.showMessageDialog(null, "Error al cargar el driver.");
           
            error.fillInStackTrace();
        }
       
    }
   
   
   /**
    * Metodo que prepara la sentencia y
    * dice como va a ser el resultSet
    * @throws java.sql.SQLException
    */
    public void crearSentencia() throws java.sql.SQLException{
     
        sentencia=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
        System.out.println("\nSentencia creada con éxito.");
    }   
   
    /**
     * Metodo que cierra la sentencia, resulset y
     * la conexion
     * @throws java.sql.SQLException
     */
    public void cerrarConexion() throws java.sql.SQLException{
        if(rs !=null){
            rs.close();
        }
        if(sentencia !=null){
            sentencia.close();
        }
        if(conn!=null){
            conn.close();
        }
        System.out.println("\nConexión cerrada con éxito.");
    }
   
     /**
      * Metodo que nos devuelve un resultSet
      * con todos los datos que devuelve la base.
      *
      * @param sql String con la select a ejecutar
      * @throws java.sql.SQLException
      */
    public void ejecutaSQL(String sql) throws java.sql.SQLException{
     
        rs= sentencia.executeQuery(sql);
    }
   
   
    /**
     * Metodo que recibe una select y
     * actualiza, inserta o borra en la bbdd.
     * Si tiene exicto develve las filas que han sido modificadas,
     * sino devuelve un -1.
     * @param sql String a ejecutar en la base de datos.
     * @return  Retorna un entero para saber las filas modificadas,
     * se usa para dejar los campos vacios en el formulario.
     * @throws java.sql.SQLException
     */
    public int updateSQL(String sql) throws java.sql.SQLException  {
        int upd = -1;
       
        try {
           
             upd = sentencia.executeUpdate(sql);
             }
        catch (SQLException e ) {
            JOptionPane.showMessageDialog(null, "Hemos tenido un problema en el updateSQL" + e.getMessage());
            upd = -1;
        }
        System.out.println("el valor de upd es=> " + upd);
        return upd;
    }
   
   
    //+ los metodos get y set


Luego para llenar el JTable, de paso al final he dejado asi el método, he modificado algo tú select:

Código: [Seleccionar]
/**
     * Metodo para buscar en el table model
     *las habitaciones disponibles en las fechas indicadas
     * @param fechaInicio
     * @param fechaSalida
     * @param buscar Recibe un String para ser ejecutado en el MySql
     * @return Devuelve un TableModel
     */
    public DefaultTableModel mostrarHabitacionesLibres(String fechaInicio, String fechaSalida) {
       
        String sql="";
   
        // SQL saber habitaciones libres
        sql = "select idhabitacion, numero,piso,descripcion,caracteristicas,precio_diario,estado,tipo_habitacion\n "
                + "from habitacion where estado='Disponible'  and idhabitacion\n"
                + "not in(select idhabitacion from reserva\n"
                + "where "
                + "'" + fechaInicio + "' not  between fecha_ingreso and  fecha_salida \n"
                + "or\n"
                + "'" + fechaSalida + "' not  between fecha_ingreso and fecha_salida\n"
                + "or\n"
                + "'" + fechaInicio + "' <fecha_ingreso\n"
                + "and\n"
                + "'" + fechaSalida + "' > fecha_ingreso \n"
                + "or\n"
                + "'" + fechaSalida + "' >fecha_salida \n"
                + "and\n"
                + "'" + fechaInicio + "' < fecha_salida)\n";
       
       //Básicamente si te fijas creo dos  array, uno para las cabeceras otro para los datos "claro el problema que no es dinámico y si un día modifico algun dominio de la tabla hay que venir y modificar el script"
       
//Declaro y instancio un modelo a null       
        DefaultTableModel modelob = null;
//Array para los titulos
        String[] titulos = {"ID",  "Numero", "Piso", "Descripcion", "Caracteristicas", "Precio Diario", "Estado", "Tipo de Habitacion"};
//Array par los datos
        String[] registro = new String [8];
        //Uso el propio constructor del Modelo, primero aun a nulo y el segundo parametro el array de los titulos
        modelob = new DefaultTableModel(null,titulos);
        try{
         
//Conecto bbdd
 
        conn.conecta();
        conn.crearSentencia();
        conn.ejecutaSQL(sql);
        while (conn.getRs().next()){
           
                registro[0] = conn.getRs().getString("idhabitacion");
                registro[1] = conn.getRs().getString("numero");
                registro[2] = conn.getRs().getString("piso");
                registro[3] = conn.getRs().getString("descripcion");
                registro[4] = conn.getRs().getString("caracteristicas");
                registro[5] = conn.getRs().getString("precio_diario");
                registro[6] = conn.getRs().getString("estado");
                registro[7] = conn.getRs().getString("tipo_habitacion");
               
                totalRegistro = totalRegistro + 1;
                System.out.println("el total registros es " +totalRegistro);
                modelob.addRow(registro); // Añado como primer parametro al modelo el array de con los datos
        }
        conn.cerrarConexion();
        } catch (SQLException e) {
            JOptionPane.showMessageDialog(null, "No se ha podido recuperar los datos desde mostrarHabitacionesLibres." + e);
        }
 
           return modelob; //Retorno modelo
     
    }   

//Creo que esta forma es más sencilla y limpia aunque tiene la pega que no es dinámica la tuya si.


Bueno Dongo también puedes observa que te he modificado la select, primero he quitado esta parte de la línea:

STR_TO_DATE('" + fechaInicio + "', '%d-%m-%Y')

No me hace falta ya que la fecha se introduce con un JDateChooose y no hace falta cambiar el orden. La segunda es que tú habías comparado  < y > con la fecha de reserva y esa fecha yo no la utilizo para este fin.

Pero me has dejado con la duda de que te pregunte sobre las select anidada, por que no te da el error de que la subselect devuelve mas de una fila. No lo entiendo, mira este ejemplo sencillo:

Código: [Seleccionar]
select idhabitacion from habitacion where (select idhabitacion from habitacion where idhabitacion > 2)
La subselect me debería devolver  o más idhabitaciones, estan en la misma columna claro, pero me responde:
Código: [Seleccionar]
12:24:18 select idhabitacion from habitacion where (select idhabitacion from habitacion where idhabitacion > 2) Error Code: 1242. Subquery returns more than 1 row 0.032 sec


¿Por que a tu select que devuelve más de una fila la subselect no te lo hace?

dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #32 en: 27 de Agosto 2014, 16:55 »
aaaa Amigo, jeje la select con la subconsulta no me da error por que uso el operador IN.

Si hago una consulta con subconsulta de este tipo, Usare la tabla habitación y la tabla reserva de tu BBDD:

Código: [Seleccionar]
SELECT * FROM habitacion WHERE idhabitacion IN( SELECT idhabitacion FROM reservas);

Me devolverá todas las filas de la tabla habitación, cuya id este en la tabla reservas.

El operador IN lo que espera es una lista de valores, pues yo le doy una lista de valores a través de una select.

Por otro lado si quiero las habitaciones que no están en la tabla reservas solo tendré  que negar el operador(NOT IN).

Resumiendo el operador IN es un operador que espera una lista de valores, y una select, no es más que... una lista de valores. El lenguaje sql es un lenguaje que si lo conoces a fondo te facilita mucho la vida...

Apostaría a que no sabías que se podía montar una sentencia de este tipo....:
Código: [Seleccionar]
SELECT concat( idhabitacion, " Numero de habitaciones: ",(SELECT count(*) FROM habitacion)) FROM habitacion

Bueno, eso es una de las cosas que yo echo de menos entre la variedad de cursos de esta web, a veces pensamos que una base de datos es para guardar datos y ya esta, y es un sofware muy poderoso con muchísimas capacidades, véase PL/SQL...

La verdad que me podría pasar horas hablando de las ventajas que tiene saber bien sql, pues a la hora de procesar datos podemos delegar muchas funciones sobre la base de datos.

Y nada yo creo que hoy en día no hay aplicación empresarial sin una base de datos por detrás por eso creo que saber sql es una cuestión fundamental para todo desarrollador.

Y nada mas, te animo a que lo estudies porque te sorprenderás de las cosas que puedes hacer con él.

Un saludo!!

P.D. Por cierto, sigo pensando que tu manera de crear el jtable es ganas de complicarse la vida....
« Última modificación: 27 de Agosto 2014, 16:59 por dongo »

dongo

  • Intermedio
  • ***
  • Mensajes: 177
    • Ver Perfil
Re:intervalos de fechas MySql para reservas en hotel
« Respuesta #33 en: 27 de Agosto 2014, 17:12 »
Por cierto a tu select en la condición es que le falta la mitad, le falta la columna de la select principal con la que vas a comparar la subselect y también le falta el operador...

Código: [Seleccionar]
select idhabitacion from habitacion where idhabitacion in (select idhabitacion from habitacion where idhabitacion > 2)


Si te fijas entre el where y la subselect, yo le he metido:
  • idhabitacion ->que es la columna con la que estoy comparando lo que me devuelve la subselect
  • in -> Es el operador de la condición

Si la ejecutas, con esas dos cosas, ya te funciona... que te haga lo que tu quieres ya es otra cosa, pero al menos ya devuelve algo...

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".