¿Alguien que sepa de Java + SQL? ¡Ayuda! :(

No sé si este es el subforo correcto, pero bueno, no pierdo nada. Tengo que hacer una TPV para entregar al final del trimestre (segundo año del CFGS ASIR) y el caso es que llevo un retraso del copón porque soy incapaz de hacer que la mierda de base de datos funcione, y sin tener los datos pues no puedo seguir trabajando en el dichoso programa, así que os comento por aquí a ver si alguien sabe arreglarlo y así puedo trabajar hasta el lunes.

Poniendo como ejemplo un método, aquí hay uno de los que no chutan. En realidad, no chuta absolutamente NADA que pida información a la base de datos. La respuesta siempre tira excepción NULL. Eso sí, la conexión a la base de datos es correcta. Por si sirve de algo, la base de datos va por phpmyadmin mediante WAMP.


private int cuantasF(){
      int cuantasfamilias=0;
       DbConnection();                     

      try
       {            
       PreparedStatement consultap;   
       String queryp = ("select count(*) from familias");                 
       consultap = conexion.prepareStatement(queryp);             
       ResultSet rsp =consultap.executeQuery();              
       rsp.last();
       cuantasfamilias=rsp.getInt(1);
       //cuantasfamilias=(Integer) rsp.getObject(1);
   
       rsp.close();
       consultap.close();
        conexion.close();
             }
          catch (Exception e)
             {
                 System.out.println("Error: " + e.getMessage());
             }   
      
      System.out.println(cuantasfamilias);
      return cuantasfamilias;
   }


Lo he intentado así, cambiando a un void sin retorno, sin el rsp.last(), con el getInt o con el "//", pero da exactamente igual, el resultado siempre es el mismo, falla y me tira la excepción con el único mensaje Error: NULL. Incluso he cambiado los nombres de las variables, puesto ; al final del select... Yo qué sé, debe ser algo tontísimo, pero el caso es que no chuta. cuantasfamilias está siempre a 0 y no puedo hacer nada.
Prueba así a ver qué tal:

private int cuantasF(){
      int cuantasfamilias=0;
       DbConnection();                     

      try
       {            
       PreparedStatement consultap;   
       String queryp = "SELECT count(*) AS total FROM familias"; //Esta consulta devuelve en total el número de filas en la tabla familias.                 
       consultap = conexion.prepareStatement(queryp);             
       ResultSet rsp =consultap.executeQuery();              
       cuantasfamilias=rsp.getInt("total");
   
       rsp.close();
       consultap.close();
                conexion.close();
             }
          catch (Exception e)
             {
                 System.out.println("Error: " + e.getMessage());
             }   
      
      System.out.println(cuantasfamilias);
      return cuantasfamilias;
   }
NachBM84 escribió:Prueba así a ver qué tal:
...


Nada, sigue igual :(
private int cuantasF(){
      int cuantasfamilias=0;
       DbConnection();                     

      try
       {            
       PreparedStatement consultap;   
       String queryp = "SELECT count(*) AS total FROM familias"; //Esta consulta devuelve en total el número de filas en la tabla familias.                 
       consultap = conexion.prepareStatement(queryp);             
       ResultSet rsp =consultap.executeQuery();           
       if(rsp.next()) cuantasfamilias=rsp.getInt("total");
   
       rsp.close();
       consultap.close();
                conexion.close();
             }
          catch (Exception e)
             {
                 System.out.println("Error: " + e.getMessage());
             }   
      
      System.out.println(cuantasfamilias);
      return cuantasfamilias;
   }


creo que te falta el rsp.next()
Ricardo007 escribió:
creo que te falta el rsp.next()


¿Dónde?

Edit: Perdón, no lo había visto en el código. Sigue sin funcionar, el mismo error de siempre...
ramulator escribió:
Ricardo007 escribió:
creo que te falta el rsp.next()


¿Dónde?



lo he puesto en el código, en la misma línea que el rsp.getint() dentro de un if()
Ricardo007 escribió:
ramulator escribió:
Ricardo007 escribió:
creo que te falta el rsp.next()


¿Dónde?



lo he puesto en el código, en la misma línea que el rsp.getint() dentro de un if()


Sí, disculpa, no lo había visto, lo comento en el edit... Pero sigue devolviendo el mismo error.
ramulator escribió:
Sí, disculpa, no lo había visto, lo comento en el edit... Pero sigue devolviendo el mismo error.



en que línea da el NullPointerExcrption??? todo parece correcto
Cuando alguna consulta no me funcionaba solia ser porque la tabla debía ir entre comillas simples, "SELECT count(*) AS total FROM 'familias' ", aunque eso era en mysql con php

Quizas ya lo hiciste pero probar las consultas directamente en la consola de sql suele ayudar a descubrir errores
Ricardo007 escribió:
ramulator escribió:
Sí, disculpa, no lo había visto, lo comento en el edit... Pero sigue devolviendo el mismo error.


en que línea da el NullPointerExcrption??? todo parece correcto

No es NullPointerException, sencillamente salta el catch Exception e, y e.getMessage() devuelve Null sin más.

Suicune escribió:Cuando alguna consulta no me funcionaba solia ser porque la tabla debía ir entre comillas simples, "SELECT count(*) AS total FROM 'familias' ", aunque eso era en mysql con php

Quizas ya lo hiciste pero probar las consultas directamente en la consola de sql suele ayudar a descubrir errores


No he probado con comillas desde el código en Java, pero vamos, que en la consola de SQL de phpmyadmin funciona la consulta sin comillas, así que eso no es...

Es extrañísimo.
Entonces probaria poner
ResultSetMetaData rsmd = rsp.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (resultSet.next()) {
    for (int i = 1; i <= columnsNumber; i++) {
        if (i > 1) System.out.print(",  ");
        String columnValue = resultSet.getString(i);
        System.out.print(columnValue + " " + rsmd.getColumnName(i));
    }
    System.out.println("");
}

después de ResultSet rsp =consultap.executeQuery(); para saber si rsp realmente contiene resultados, eso lo encontré aquí http://stackoverflow.com/questions/2422 ... -resultset
Pon e.printStackTrace() para ver el mensaje de error y pega lo.

Aunque sospecho que puede ser.
Suicune escribió:Entonces probaria poner
ResultSetMetaData rsmd = rsp.getMetaData();
int columnsNumber = rsmd.getColumnCount();
while (resultSet.next()) {
    for (int i = 1; i <= columnsNumber; i++) {
        if (i > 1) System.out.print(",  ");
        String columnValue = resultSet.getString(i);
        System.out.print(columnValue + " " + rsmd.getColumnName(i));
    }
    System.out.println("");
}

después de ResultSet rsp =consultap.executeQuery(); para saber si rsp realmente contiene resultados, eso lo encontré aquí http://stackoverflow.com/questions/2422 ... -resultset


Exactamente el mismo resultado...

Voy dando el finde por perdido xD

¡Muchas gracias a todos por la ayuda!

Edit: Vale, con el printStackTrace sí que me saca el NullPointer (disculpad pero la verdad es que no soy muy ducho en Java todavía):

java.lang.NullPointerException
   at __TPV.GestionBar.cuantasF(GestionBar.java:876)
   at __TPV.GestionBar.<init>(GestionBar.java:827)
   at __TPV.GestionBar$1.run(GestionBar.java:111)
   at java.awt.event.InvocationEvent.dispatch(Unknown Source)
   at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
   at java.awt.EventQueue.access$500(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
   at java.awt.EventQueue.dispatchEvent(Unknown Source)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.run(Unknown Source)
Que va no lo des por perdido

Prueba
Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM familias);
En lugar de preparwdstatement. Y pon lo que te dije para ver donde esta el error


Que hay aquí? (Es la linea)
GestionBar.java:876
Budathecat escribió:Que va no lo des por perdido

Prueba
Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT * FROM familias);
En lugar de preparwdstatement. Y pon lo que te dije para ver donde esta el error

Que hay aquí? (Es la linea)
GestionBar.java:876


Sigue devolviendo el mismo error.

En la línea 876 está esto:

consultap = conexion.prepareStatement(queryp);

Con tu código los errores son los siguientes:

Error: null
   at __TPV.GestionBar.cuantasF(GestionBar.java:879)
   at __TPV.GestionBar.<init>(GestionBar.java:829)
   at __TPV.GestionBar$1.run(GestionBar.java:113)
   at java.awt.event.InvocationEvent.dispatch(Unknown Source)
   at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
   at java.awt.EventQueue.access$500(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.awt.EventQueue$3.run(Unknown Source)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
   at java.awt.EventQueue.dispatchEvent(Unknown Source)
   at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
   at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)0

   at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
   at java.awt.EventDispatchThread.run(Unknown Source)


Lo he adaptado tal que así:

try
       {            
       //PreparedStatement consultap;   
       //String queryp = ("select count(*) from familias");   
         
         Statement stmt = (Statement) conexion.createStatement();
         ResultSet rsp = stmt.executeQuery("SELECT * FROM familias");

         
       //consultap = conexion.prepareStatement(queryp);             
       //ResultSet rsp =consultap.executeQuery();
       
       rsp.last();
       cuantasfamilias=rsp.getInt(1);
       //cuantasfamilias=(Integer) rsp.getObject(1);
Pero analizando el trozo de codigo que pones, puedes ir desde el principio al final para encontrar donde está el error, aunque te diga que algo está en null lo que se ejecute antes de eso debe estar bien. Si pones unos print despues de cada cosa vas a saber hasta donde llega antes del null

Por ejemplo en tu codigo original
private int cuantasF(){
      int cuantasfamilias=0;
       DbConnection();                     

      try
       {           
       PreparedStatement consultap;
        System.out.println("consultap declarada");
       String queryp = ("select count(*) from familias");                 
       consultap = conexion.prepareStatement(queryp);
          System.out.println("query preparada");             
       ResultSet rsp =consultap.executeQuery();
         System.out.println("query ejecutada");             
       rsp.last();
          System.out.println("rsp last");
       cuantasfamilias=rsp.getInt(1);
         System.out.println("rsp getInt etc..");
       //cuantasfamilias=(Integer) rsp.getObject(1);
   
       rsp.close();
       consultap.close();
        conexion.close();
             }
          catch (Exception e)
             {
                 System.out.println("Error: " + e.getMessage());
             }   
     
      System.out.println(cuantasfamilias);
      return cuantasfamilias;
   }


Te va a dar el mismo error pero al menos sabras donde mirar exactamente
Porque no haces un debug en esa parte para ver que falla?
Como abres la conexión?
Enseñamos el dbconnection()
@Suicune esta es la respuesta por consola de tu código:

Conexión a base de datos tpv OK

consultap declarada
Error: null
0


@seaman ¿cómo hago eso? [+risas]

@alienvita2 ahí va:

public void DbConnection() {
      String bd = "tpv";
       String login = "root";
       String password = "";
       String url = "jdbc:mysql://localhost/"+bd;    
      try{
         //obtenemos el driver para mysql
         Class.forName("com.mysql.jdbc.Driver");
         //obtenemos la conexión
         Connection conexion = DriverManager.getConnection(url,login,password);

         if (conexion!=null){
            System.out.println("Conexión a base de datos "+bd+" OK\n");
         }
      }
      catch(SQLException e){
         System.out.println(e);
      }catch(ClassNotFoundException e){
         System.out.println(e);
      }catch(Exception e){
         System.out.println(e);
      }
   }
Es mejor aun uses e.print. ... En lugar de imprimir el mensaje de error. Aunque ahí no falla

Con debug es más rápido pero no lo va a saber usar.
Te falla la conexión.
La abres en el método conexióndb

Y luego la usas en el otro método sin pasarela y sin ser una variable estática.

Prueba a cambiar esto
Connection conexion = DriverManager.getConnection(url,login,password);

Por esto

conexion = DriverManager.getConnection(url,login,password);
Si estás con java, lo mejor es usar o Netbeans o Eclipse.

De todas formas, a ver, con algunos programas te permite ver que valor tienen las variables.
Al poner un breakpoint donde interesa podrás saber porque te da null.
Yo aún no estoy con bases de datos en Java. Por eso no puedo ayudarte muy bien.

http://puntocomnoesunlenguaje.blogspot. ... -java.html
Efectivamente, uso Eclipse.

Budathecat escribió:Es mejor aun uses e.print. ... En lugar de imprimir el mensaje de error. Aunque ahí no falla

Con debug es más rápido pero no lo va a saber usar.
Te falla la conexión.
La abres en el método conexióndb

Y luego la usas en el otro método sin pasarela y sin ser una variable estática.

Prueba a cambiar esto
Connection conexion = DriverManager.getConnection(url,login,password);

Por esto

conexion = DriverManager.getConnection(url,login,password);


Creo que esto ha solucionado el problema, voy a trastear un poco y os cuento :D

Edit: Diosssssssssss, sí que funciona, ¡un millón de gracias! ¡Al final sí que voy a poder aprovechar el finde! [sonrisa]
De nada. Pero lo entendiste?
Budathecat escribió:De nada. Pero lo entendiste?


El problema es que se declara como variable estática y no debería, ¿no?
ramulator escribió:
Budathecat escribió:De nada. Pero lo entendiste?


El problema es que se declara como variable estática y no debería, ¿no?


No, más bien al contrario.

Imagino que los metodos DbConnection y CuantasF están en la misma clase, y que en esa clase tienes una variable gobal llamada conexion.

El problema está en que cuando en el DbConnection pones

Connection conexion = DriverManager.getConnection(url,login,password);

Estás creando una nueva variable, que no es tu variable global conexion. Esa nueva variable tendrá su vida en ese método, y al terminar sus instrucciones, desaparecerá.

Cuando te han dicho que pongas esto:

conexion = DriverManager.getConnection(url,login,password);

Ahí sí que estás dando valor a la variable golbal de tu clase. Por eso al terminar el método DbConnection, ya no te da null, porque mantiene el valor que le has dado en el método.

Bueno, así lo entiendo yo. Si me dices que DbConnection está en otra clase distinta, entonces no entiendo como te funciona, si no creas ningún objeto del tipo DbConnection... [+risas]

Aquí te dejo un link sobre las variables globales y locales. No es java, pero el código se entiende:

https://msdn.microsoft.com/es-es/librar ... 90%29.aspx
DevilKeeper escribió:
ramulator escribió:
Budathecat escribió:De nada. Pero lo entendiste?


El problema es que se declara como variable estática y no debería, ¿no?


No, más bien al contrario.

Imagino que los metodos DbConnection y CuantasF están en la misma clase, y que en esa clase tienes una variable gobal llamada conexion.

El problema está en que cuando en el DbConnection pones

Connection conexion = DriverManager.getConnection(url,login,password);

Estás creando una nueva variable, que no es tu variable global conexion. Esa nueva variable tendrá su vida en ese método, y al terminar sus instrucciones, desaparecerá.

Cuando te han dicho que pongas esto:

conexion = DriverManager.getConnection(url,login,password);

Ahí sí que estás dando valor a la variable golbal de tu clase. Por eso al terminar el método DbConnection, ya no te da null, porque mantiene el valor que le has dado en el método.

Bueno, así lo entiendo yo. Si me dices que DbConnection está en otra clase distinta, entonces no entiendo como te funciona, si no creas ningún objeto del tipo DbConnection... [+risas]

Aquí te dejo un link sobre las variables globales y locales. No es java, pero el código se entiende:

https://msdn.microsoft.com/es-es/librar ... 90%29.aspx


Vale genial, ¡entendido!

Efectivamente, está todo en una clase. Con el tema de variables estáticas/dinámicas y tal me estaba perdiendo, pero ya he entendido a lo que te refieres.

De todos modos, lo tengo todo un poco "caótico" porque realmente hemos empezado a programar Java este curso, pero no es hasta hace menos de un mes que hemos enlazado a base de datos y además con un código que nos ha dado el profesor (que por lo que se ve estaba mal xD).

Gracias por las lecciones :D
25 respuestas