Problema con Le Date Java Access DB

di il
19 risposte

Problema con Le Date Java Access DB

Ciao Ragazzi,
ho fatto un programma per taskare le varie persone sotto determinati processi in azienda.
Il programma funziona tutto perfettamente, TRANNE un solo bottone, che è il Task-Out, prima del codice vi spiego cosa dovrebbe fare quel bottone :
- Memorizzare la riga selezionata in una tabella
- mettere nella colonna "out" data e ora del momento in cui è stato cliccato il bottone
- Successivamente, nella colonna total fa la differenza tra contenuto della colonna out e della colonna in e mi mostra per quanto tempo quell'utente è stato loggato.

L'errore in questione è :

java.lang.ClassCastException: class java.lang.String cannot be cast to class java.sql.Timestamp (java.lang.String is in module java.base of loader 'bootstrap'; java.sql.Timestamp is in module java.sql of loader 'platform')

Codice impattato :
private void tsk_out_btnActionPerformed(java.awt.event.ActionEvent evt) {                                            
        String query = null;
        int row = table_pane.getSelectedRow();
        int column = table_pane.getSelectedColumn();
        Date date = new Date();
        java.sql.Date sqlDate = new java.sql.Date(date.getTime());
        String index = table_pane.getValueAt(row, 0).toString();
        
        try {
            
            if(table_pane.isRowSelected(row)==true){
                Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                String path = "\\\\mioindirizzo\\Produttività\\03_Waves\\Time On Task\\Time On Task DB\\TimeOnTask.mdb";
                String url = "jdbc:ucanaccess://"+path;
                               
                java.sql.Timestamp startDate = (java.sql.Timestamp) (table_pane.getValueAt(row, 4));
                
                float numOfMins = (sqlDate.getTime() - startDate.getTime())/1000/60;
                float numOfHours = numOfMins/60;
                float numOfDays = numOfHours/24;
                
                String totalStr = String.format("%d days, %d hours, %d minutes", (int) Math.floor(numOfDays),
                        (int) Math.floor(numOfHours%24), (int) Math.floor(numOfMins%60));
               
                
                Connection conn = DriverManager.getConnection(url);
            
                query = "UPDATE TimeOnTask SET Status = 'Terminated', out = ?, total = '" + totalStr + "' WHERE index = '"+index+"'";
                pst = conn.prepareStatement(query);
                pst.setDate(1, sqlDate);
                pst.executeUpdate();
                pst.close();
                }
Quello che ho capito è che da qualche parte in questo spezzone il programma si aspetta una stringa ed è incompatibile con java.sql.Timestamp.
Potreste aiutarmi a capire cosa c'è di sbagliato?

Grazie mille in anticipo,
Saluti.
Carlo.

19 Risposte

  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


    java.lang.ClassCastException: class java.lang.String cannot be cast to class java.sql.Timestamp (java.lang.String is in module java.base of loader 'bootstrap'; java.sql.Timestamp is in module java.sql of loader 'platform')
    Direi che la riga incriminata è questa:
                         
                    java.sql.Timestamp startDate = (java.sql.Timestamp) (table_pane.getValueAt(row, 4));
    
    E la questione è sostanzialmente che in quella cella (riga row, colonna 4) c'è una stringa e non un oggetto Timestamp, che OVVIAMENTE non sono in relazione e non possono essere certo convertiti l'uno nell'altro tramite banale "cast".

    Quindi la questione diventa: quella stringa va parsata per ottenere un Date (java.util.Date) e poi da lì (se serve) un Timestamp. E per fare un parsing la stringa deve essere in un formato noto o comunque determinabile in qualche modo.
    Se quella cella è editabile (come immagino), in che formato l'utente scrive la data??
  • Re: Problema con Le Date Java Access DB

    Ciao Andrea,

    Grazie per la risposta, allora, la data non viene inserita a mano ma viene presa in automatico al momento della pressione sul pulsante register.
    Grazie alla tua risposta, mi è venuto il dubbio di aver dimenticato, sul database di settare la colonna delle date con il formato "Date" e devo aver tenuto quei campi formattati come "Testo Lungo".
    Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
    Questo è il modo in cui il programma formatta la data, ma se il db è formattato su testo, probabilmente il problema è quello.
    Perchè ricordo che a casa andava tutto, ma in azienda devo essermi dimenticato di modificare la formattazione delle colonne.

    Carlo B.
  • Re: Problema con Le Date Java Access DB

    No niente.

    I campi sono formattati giusti con Data/Ora. No allora il problema non è il DB.
    Però è strano a casa andava tutto ed era esattamente uguale a qui, qualcosa mi sfugge....
  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


    I campi sono formattati giusti con Data/Ora. No allora il problema non è il DB.
    Però è strano a casa andava tutto ed era esattamente uguale a qui, qualcosa mi sfugge....
    Nella cella ( table_pane.getValueAt(row, 4) ) continua ad esserci un String?? Perché se sì, continuo a ripetere che NON puoi fare un cast a Timestamp.
  • Re: Problema con Le Date Java Access DB

    Index mio task in status out total
    1 | pippo | Team Lead | 12/05/2019 17:56:57 | Terminated | 12/05/2019 19:10:56 | 0 days, 1 hours, 13 minutes

    Sopra puoi vedere il risultato di output come usciva la riga completa funzionante.
    Come vedi alla voce OUT = il formato è : dd/MM/yyyy hh:mm:ss

    Mentre la riga row è dichiarata come :
    int row = table_pane.getSelectedRow();
    Poi ho capito che il problema è in quella riga di cast ma non so come modificarla, qualsiasi modifica rimanda un errore, pare essere valida solo quella con il casting che però dà l'errore riportato sopra.

    Cosa dovrei mettere al posto di quel getValueAt? oppure al posto del casting?
    Anche a livello di variabili non vedo stringhe, almeno, non mi sembra così a occhio..i campi delle date sono tutti settati come Date anche sul DB.
  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


    Cosa dovrei mettere al posto di quel getValueAt? oppure al posto del casting?
    Il problema non è il getValueAt (questo comunque lo devi fare per prendere l'oggetto nella cella). Il problema è il cast. Se l'oggetto nella cella è realmente un java.lang.String, non c'è alcun "cast" (nel senso dell'operatore di casting) che puoi fare per ottenere un Timestamp.
    Devi fare un "parsing", con un DateFormat/SimpleDateFormat (che ti dà un java.util.Date, NON un java.sql.Timestamp). E visto che quel Timestamp lo volevi usare solo per fare una differenza sugli istanti del tempo .... non serve nemmeno un Timestamp, basterebbe un Date appunto.

    carlo.b ha scritto:


    Anche a livello di variabili non vedo stringhe, almeno, non mi sembra così a occhio..i campi delle date sono tutti settati come Date anche sul DB.
    Beh, COME viene inserito (e preso come/da dove) il valore nella cella??
  • Re: Problema con Le Date Java Access DB

    Ah ok, ecco aspetta.
    Questa è la porzione di codice, riferita al bottone di inserimento, che mi riempie le celle del DB :
    private void sc_btnActionPerformed(java.awt.event.ActionEvent evt) {                                       
            String usr = usr_txt.getText();
            String tsk = sc_list.getSelectedValue().toString();
            String sts = "Active";
            Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
            String query = null;
            
            try {
                Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                String path = "\\\\mioindirizzo\\Produttività\\03_Waves\\Time On Task\\Time On Task DB\\TimeOnTask.mdb";
                String url = "jdbc:ucanaccess://"+path;
                Connection conn = DriverManager.getConnection(url);
                
                if (usr_txt.getText().trim().isEmpty()){
                JOptionPane.showMessageDialog(null, "Username Field Requested");
                }else if(sc_list.getSelectedValue()== null){
                    JOptionPane.showMessageDialog(null, "Please Select task in");
                }else{
                    query = "INSERT INTO TimeOnTask(mio, task, in, status) VALUES(?,?,?,?)";
                    pst = conn.prepareStatement(query);
                    
                    pst.setString(1, usr);
                    pst.setString(2, tsk);
                    pst.setDate(3, sqlDate);
                    pst.setString(4, sts);
                    pst.executeUpdate();
                    JOptionPane.showMessageDialog(null,"Dipendente "+usr+" Registrato come "+tsk);
                    
                    usr_txt.setText(null);
                    sc_list.setSelectedIndex(0);
                    pst.close();
                }
            }catch(Exception e){
                JOptionPane.showMessageDialog(null,"User Not Registered, ERROR : "+e);
                System.out.println("ERROR : "+e);
            }
    Mentre questa è la parte di codice che inserisce tutto nella tabella :
    query = "INSERT INTO TimeOnTask(mio, task, in, status) VALUES(?,?,?,?)";
                    pst = conn.prepareStatement(query);
                    
                    pst.setString(1, usr);
                    pst.setString(2, tsk);
                    pst.setDate(3, sqlDate);
                    pst.setString(4, sts);
                    pst.executeUpdate();
    La data nel DB viene messa automaticamente secondo il modo in cui ho diachiarato la variabile di data :
    Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
    Non riesco a dirti altro purtroppo..anche perchè sulla gestione delle date non sono bravo, quella parte l'ha gestita un amico..dato che io mi ero bloccato.. La cella è di formato DATA/ORA
  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


    Questa è la porzione di codice, riferita al bottone di inserimento, che mi riempie le celle del DB :
    Il problema non è tanto quello.

    pst.setDate(3, sqlDate);

    Questo di per sé è corretto. (occhio solo a una cosa: java.sql.Date concettualmente si usa per mapparlo sul tipo DATE di JDBC che ha solo la data, NON l'ora. Ma non conosco Access, quindi non so dire ora come lo possa trattare davvero). Sarebbe più corretto un Timestamp.

    Quello che chiedevo io è: COME viene inserita la data in quel table_pane
  • Re: Problema con Le Date Java Access DB

    La table pane è settata su 0 righe e non fa altro che prendere il model dalla tabella del db :
    private void updateTsk(){
        String query = null;
        try {
            Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
            String path = "\\\\mioindirizzo\\Produttività\\03_Waves\\Time On Task\\Time On Task DB\\TimeOnTask.mdb";
            String url = "jdbc:ucanaccess://"+path;
            Connection conn = DriverManager.getConnection(url);
            
            query = "select * from TimeOnTask";
            pst = conn.prepareStatement(query);
            rs = pst.executeQuery();
            table_pane.setModel(DbUtils.resultSetToTableModel(rs));
            table_pane.getColumnModel().getColumn(0).setWidth(0);
            table_pane.getColumnModel().getColumn(0).setMaxWidth(0);
            table_pane.getColumnModel().getColumn(0).setMinWidth(0);
            table_pane.getColumnModel().getColumn(0).setPreferredWidth(0);
            pst.close();
            
            }catch(Exception e){
            JOptionPane.showMessageDialog(null, e);
            }
        }
    Le table_pane prima di pst.close si riferiscono solo alla colonna indice del DB che genera un numero automatico univoco per ogni riga e che viene quindi nascosta nella jtable.
    Mentre la colonna di data nel DB viene inserita automaticamente con lo script che ti ho mostrato prima.
    La jtable non fa altro che mstrare il contenuto del DB, non so se questo può esserti utile...
  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


            table_pane.setModel(DbUtils.resultSetToTableModel(rs));
    Ahhh e quel resultSetToTableModel come tira fuori i dati delle colonne dal ResultSet?? Sempre e solo come String? O sfrutta i metadati del ResultSet (il ResultSetMetaData che descrive le colonne)?
    Ecco, questo è il punto.
  • Re: Problema con Le Date Java Access DB

    Ecco adesso ti posto il passaggio, perchè avendo sfruttato anche Netbeans copiarti tutto il codice stai qui 3 giorni, ti prendo solo i pezzi che servono, aspetta che ci provo. (Ora sono a casa, e da netbeans il programma funziona, ti posto quello che vediamo se varia qualcosa dal precedente) :

    Inizio :
    public class MainTot extends javax.swing.JFrame {
        
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        PreparedStatement pst = null;
        
        public MainTot() {
            initComponents();
        }
    Codice per il Bottone "Register Data in DB Pack" per il processo di Pack :
    private void pa_btnActionPerformed(java.awt.event.ActionEvent evt) {                                       
            String usr = usr_txt.getText();
            String tsk = pa_list.getSelectedValue().toString();
            String sts = "Active";
            //SimpleDateFormat df = new SimpleDateFormat("dd-MM-YYYY HH:mm");
            Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
            String query = null;
            
            try {
                Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                String path = "C:\\Users\\pc\\Documents\\NetBeansProjects\\TimeOnTask2\\Database\\TimeOnTask.mdb";
                String url = "jdbc:ucanaccess://"+path;
                Connection conn = DriverManager.getConnection(url);
                
                if (usr_txt.getText().trim().isEmpty()){
                JOptionPane.showMessageDialog(null, "Username Field Requested");
                }else if(pa_list.getSelectedValue()== null){
                    JOptionPane.showMessageDialog(null, "Please Select task in");
                }else{
                    query = "INSERT INTO TimeOnTask(mio, task, in, status) VALUES(?,?,?,?)";
                    pst = conn.prepareStatement(query);
                    
                    pst.setString(1, usr);
                    pst.setString(2, tsk);
                    pst.setDate(3, sqlDate);
                    pst.setString(4, sts);
                    pst.executeUpdate();
                    JOptionPane.showMessageDialog(null,"Dipendente "+usr+" Registrato come "+tsk);
                    
                    usr_txt.setText(null);
                    pa_list.setSelectedIndex(0);
                    pst.close();
                }
            }catch(Exception e){
                JOptionPane.showMessageDialog(null,"User Not Registered, ERROR : "+e);
                System.out.println("ERROR : "+e);
            }
            
            updateTsk();
        }
    Ho lavorato un saccon variabili locali usando Netbeans.

    Ora il codice che dichiara le variabili locali :
    String usr = usr_txt.getText();
            String tsk = pa_list.getSelectedValue().toString();
            String sts = "Active";
            //SimpleDateFormat df = new SimpleDateFormat("dd-MM-YYYY HH:mm");
            Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
            String query = null;
    Successivamente inizio un try and catch per istanziare un collegamento con il DB :
    try {
                Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                String path = "C:\\Users\\pc\\Documents\\NetBeansProjects\\TimeOnTask2\\Database\\TimeOnTask.mdb";
                String url = "jdbc:ucanaccess://"+path;
                Connection conn = DriverManager.getConnection(url);
    Poi inizio a scrivere cosa deve fare quel bottone mediante condizioni IF e ELSE
    if (usr_txt.getText().trim().isEmpty()){
                JOptionPane.showMessageDialog(null, "Username Field Requested");
                }else if(pa_list.getSelectedValue()== null){
                    JOptionPane.showMessageDialog(null, "Please Select task in");
                }else{
                    query = "INSERT INTO TimeOnTask(mio, task, in, status) VALUES(?,?,?,?)";
                    pst = conn.prepareStatement(query);
                    
                    pst.setString(1, usr);
                    pst.setString(2, tsk);
                    pst.setDate(3, sqlDate);
                    pst.setString(4, sts);
                    pst.executeUpdate();
                    JOptionPane.showMessageDialog(null,"Dipendente "+usr+" Registrato come "+tsk);
    Infine dopo aver eseguito tutto resetta tutti i campi al valore iniziale :
    usr_txt.setText(null);
                    pa_list.setSelectedIndex(0);
                    pst.close();
    Dopodichè aggiorna la jtable con i nuovi valori presi dal DB :
    }catch(Exception e){
                JOptionPane.showMessageDialog(null,"User Not Registered, ERROR : "+e);
                System.out.println("ERROR : "+e);
            }
            
            updateTsk();
        }
    Quindi il bottone di registrazione compila il DB con i dati inseriti nei vari campi tranne lo status che è fisso e la data che viene generata automaticamente al momento del clic ed inserita nel DB usando la formattazione :
    Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
    e:
    pst.setDate(3, sqlDate);
    Spero sia un pò più chiaro come vengono inseriti i dati nel db e poi ripresi dalla jtable..Il ResultSet credo funzioni estraendole come stringhe, perche non ricordo di aver mai usato ResultSetMetaData
  • Re: Problema con Le Date Java Access DB

    Visto che ci sono incollo qui anche il bottone che non risulta funzionante nel primo post :
    private void tsk_out_btnActionPerformed(java.awt.event.ActionEvent evt) {                                            
            String query = null;
            int row = table_pane.getSelectedRow();
            int column = table_pane.getSelectedColumn();
            Date date = new Date();
            java.sql.Date sqlDate = new java.sql.Date(date.getTime());
            String index = table_pane.getValueAt(row, 0).toString();
            
            try {
                
                if(table_pane.isRowSelected(row)==true){
                    Class.forName("net.ucanaccess.jdbc.UcanaccessDriver");
                    String path = "C:\\Users\\pc\\Documents\\NetBeansProjects\\TimeOnTask2\\Database\\TimeOnTask.mdb";
                    String url = "jdbc:ucanaccess://"+path;
                                   
                    java.sql.Timestamp startDate = (java.sql.Timestamp) table_pane.getValueAt(row, 4);
                    
                    float numOfMins = (sqlDate.getTime() - startDate.getTime())/1000/60;
                    float numOfHours = numOfMins/60;
                    float numOfDays = numOfHours/24;
                    
                    String totalStr = String.format("%d days, %d hours, %d minutes", (int) Math.floor(numOfDays),
                            (int) Math.floor(numOfHours%24), (int) Math.floor(numOfMins%60));
                   
                    
                    Connection conn = DriverManager.getConnection(url);
                
                    query = "UPDATE TimeOnTask SET Status = 'Terminated', out = ?, total = '" + totalStr + "' WHERE index = '"+index+"'";
                    pst = conn.prepareStatement(query);
                    pst.setDate(1, sqlDate);
                    pst.executeUpdate();
                    pst.close();
                    }
                
                updateTsk();
    Stranamente qui funziona tutto, eppure....il cast è lo stesso.....
  • Re: Problema con Le Date Java Access DB

    Forse ho trovato la differenza...
    CODICE NON FUNZIONANTE :
    java.sql.Timestamp startDate = (java.sql.Timestamp) (table_pane.getValueAt(row, 4));
    CODICE FUNZIONANTE :
    java.sql.Timestamp startDate = (java.sql.Timestamp)table_pane.getValueAt(row, 4);
    Potrebbe essere che l'errore sia nelle () di : (table_pane.getValueAt(row, 4))?
  • Re: Problema con Le Date Java Access DB

    carlo.b ha scritto:


    java.sql.Timestamp startDate = (java.sql.Timestamp) (table_pane.getValueAt(row, 4));
    java.sql.Timestamp startDate = (java.sql.Timestamp)table_pane.getValueAt(row, 4);
    No, queste due righe sono perfettamente "uguali" per il compilatore. L'accesso ad un membro con il "." è comunque più prioritario dell'operatore di cast. Quindi quelle parentesi in più NON cambiano assolutamente la semantica della espressione.

    Pertanto NON è di certo quello il problema.

    E lo ripeto, il nocciolo è: COSA fa quel DbUtils.resultSetToTableModel(rs) ?? 1)Tira fuori tutto quanto solo come String (con il getString() del ResultSet) ; 2)Usa il getObject() ; 3)Sfrutta intelligentemente i meta-dati del ResultSet ?

    Perché se 1) è un grosso problema in generale. Hai tutto come String, è un casino gestire dati in quel modo (pensa ai numeri e ancora peggio alle date..).
    Se è il 2) può essere appropriato nel senso che il getObject() di ResultSet fornisce generalmente l'oggetto "giusto" (es. un Integer o un String o un java.sql.Date, ecc..) ma a patto che il driver JDBC "mappi" i tipi in modo giusto e soprattutto la base dati "sotto" sia corretta/coerente per quello che vuoi fare.
    Se già per qualche motivo la base dati ha quella colonna della data come es. VARCHAR, allora NON è certo il getObject() che ti salverebbe ...


    Quindi:
    - verifica bene cosa hai "sotto" al livello della base dati
    - verifica cosa fa (e di chi è) quel DbUtils.resultSetToTableModel
Devi accedere o registrarti per scrivere nel forum
19 risposte