entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

Aplicación de java(.jar) compilada no se puede conectar a base de datos

Buenos días.

He finalizado con la realización de un proyecto informático que consiste en la importación de archivos en Excel, a una base de datos me Microsoft Access, usando APACHE POI para el manejo de los archivos xlxs, y de JDBC-ODBC para la conexión con los archivos MDB(de acess), Para el mismo, he usado NetBeans 8.0.2 como entorno de desarrolo integrado.

Durante la ejecución del proyecto informático en el IDE, se aprecia un correcto funcionamiento durante la importación, validación de campos, generación de LOGS y salida de archivos de historial, así como también la correcta inserción en la base de datos en Access.

Sin embargo, al realizar la compilación del proyecto en un archivo .JAR, la conexión se pierde con JDBC-ODBC, arrojándome la Excepcción
java.lang.ClassNotFoundException.

El código fuente encargado de esta conexión es el siguiente:

package Controlador;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import javax.swing.JOptionPane;

public class Conexion {
    /** 
     * @author  Pedro Ramos Millán - Hospital Regional de Alta Especialidad de Zumpango
     * @version 1.0
     * Propósito: Realizar la conexión a una base de datos de Microsoft Access mediante JDBC-ODBC
     */

public  static Connection conectar(String xPath) {//En este método recupero la ruta seleccionada del archivo mdb o accdb
    /*Validación de archivo Access*/
    String extensionBD=xPath.substring(xPath.lastIndexOf("."));//aquí recupero únicamente la extensión
    if(extensionBD.equals(".mdb")||extensionBD.equals(".accdb")){//si es alguna que pertenezca a Access

    try {
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//llamamos la clase del driver
        String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + xPath;//defino la ruta y el driver
        Connection conn = DriverManager.getConnection(url, "", "");//obtengo la conexión de la ruta y el driver

        //Connection conn=DriverManager.getConnection("jdbc:ucanaccess://"+xPath); 
        System.out.println("Conexión Exitosa con la base "+xPath+" (Extensión: "+extensionBD+")");
        //Etapa de generación de LOG
                        Controlador.ClaseLog.agregar("Conexión Exitosa con la base "+xPath+" (Extensión: "+extensionBD);
                        Controlador.ClaseLog.generaArchivo();
                        //Etapa de generación de LOG
        return conn;//se retorna la conexión
    } catch (SQLException sql) {//Si aparece una SQLExeption 
        sql.printStackTrace();//imprimo traza de error, y notifico al usuario
        JOptionPane.showMessageDialog(null, "La Base de datos seleccionada está dañada, no es la base de datos del SAEH, "
                + "o no se encuentras los campos necesario para insertar, favor de verificar, ","Aviso de Base de datos",0);
        return null;//no retorno nada
}   catch (ClassNotFoundException ex) {//Si no encuentra la clase de conexión, mensaje a usuario e impresión de traza de error
        JOptionPane.showMessageDialog(null, "Error de conexión con la Base de datos","Atención BD",0);
        JOptionPane.showMessageDialog(null, ex,"Error",0);
        ex.printStackTrace();
        return null;
    }//Fin de catch
    }//fin de if de extensión
    else{//en caso de que ninguna de las extensiones proporcionadas sean de Access, Se notifica al usuario
    JOptionPane.showMessageDialog(null, "La extensión "+extensionBD+" no es válida. "
            + "Seleccione un archivo de base de datos válido","Atención",0);
        return null;//no se retorna nada
    }//fin de else
}//fin de método    
    public static void main(String[]ar){
        try {
            Scanner leer=new Scanner(System.in);
            Connection conn=Conexion.conectar("F:\\PRUEBAS\\SAEH1515.mdb");
            Statement sta=conn.createStatement();
            String sint=leer.nextLine();
            boolean exec=sta.execute(sint);
            conn.commit();
               conn.close();
        } catch (Exception e) {
        e.printStackTrace();
        }
    }
}//fin de clase

Como dato adicional, JDBC-ODBC NO requiere de ningún Driver o Jar adicional al proyecto para su funcionamiento dentro de NETBEANS entonces,Mi pregunta es:
¿Es necesaria la configuración de alguna característica en NETBEANS para compilar el archivo de salida?

De antemano, agradezco su amable atención, comunidad de Entre Desarrolladores, Saludos

MitsuGami comentado Ene 11, 2016

¿Qué versión de Java usas? Pega también el rastreo de pila de la excepción para poder ver con detalle.

pWolfman_furry29 comentado Ene 11, 2016

Muchas gracias por responder @migamipe.
Utilizo la versión de 7 de JDK.

En NetBeans no se muestra ningún rastreo de error dentro de la consola, pareciera que todo es correcto, aunque, ¿Es posible imprimir en algún archivo esta traza de error, o general un LOG con la aplicación ya compilada, con el fin de conocer a detalle la línea de código en la que la aplicación se ha detenido?

De antemano, muchas gracias por tu amable atención

MitsuGami comentado Ene 11, 2016

Puedes escribir la excepción en un log o puedes correr el JAR desde la terminal para que puedas ver el rastreo de pila.

pWolfman_furry29 comentado Ene 11, 2016

Gracias @migamipe:

La trazad de error que me arroja la consola es la siguiente:

D:\NetBeansProjects\FrmHraez\dist>java -jar FrmHraez.jar
java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Unknown Source)
        at Controlador.Conexion.conectar(Conexion.java:23)
        at Controlador.ValidaCedula.existeCedula(ValidaCedula.java:26)
        at Controlador.XLSX.processDataExcel(XLSX.java:804)
        at Vista.InternalImportarLayout.btnAceptarActionPerformed(InternalImportarLayout.java:222)
        at Vista.InternalImportarLayout.access$200(InternalImportarLayout.java:19)
        at Vista.InternalImportarLayout$3.actionPerformed(InternalImportarLayout.java:82)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(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.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue$4.run(Unknown Source)
        at java.awt.EventQueue$4.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)
java.lang.NullPointerException
        at Controlador.ValidaCedula.existeCedula(ValidaCedula.java:27)
        at Controlador.XLSX.processDataExcel(XLSX.java:804)
        at Vista.InternalImportarLayout.btnAceptarActionPerformed(InternalImportarLayout.java:222)
        at Vista.InternalImportarLayout.access$200(InternalImportarLayout.java:19)
        at Vista.InternalImportarLayout$3.actionPerformed(InternalImportarLayout.java:82)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(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.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue$4.run(Unknown Source)
        at java.awt.EventQueue$4.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)

2 Respuestas

3votos

MitsuGami Puntos8010

Siempre hay inconvenientes con JDBC-ODBC debido a que es una tecnología prácticamente obsoleta. La razón por la que corre en NetBeans y no como standalone generalmente se debe a cuestión de rutas (por eso se recomienda usar relativas en lugar de absolutas).

La mejor opción que tienes es usar UCanAccess, que es una librería para conectarse a MS Access sin necesidad de JDBC-ODBC. Esto te será de gran ventaja porque si más adelante, en el hospital desean migrar a Java 8, tu aplicación no funcionará debido a que en Java 8 se ha removido JDBC-ODBC.

Usar UCanAccess realmente es muy sencillo y solo necesitarás hacer unos pequeños cambios en tu código para tenerlo funcional y compatible con futuras versiones de Java.

PD: No uses MS Access para aplicaciones reales. MS Access no es una base de datos y la integridad de los datos no estará asegurada. Usa siempre una base de datos madura, sea SQL o NoSQL.

bl4z3r comentado Ene 12, 2016

@migamipe te hago una corrección: MS Access es una base de datos y ofrece integridad de datos. Si tienes el tiempo de jugar con ella, vas a ver que tiene restricciones, claves primarias y foráneas, índices, procedimientos almacenados, funciones y otras cosas mas. No se si tiene disparadores. Lo que se que no tiene es transaccionalidad, concurrencia y hacerla distribuida.

MitsuGami comentado Ene 12, 2016

MS Access NO es una base de datos, espero se entienda el tono. Hasta donde tengo entendido, MS Access falla en:

  • Compatibilidad: solo funciona en Windows.
  • Particionamiento: MySQL tiene soporte para particionamiento Range y Composite. MS Access no.
  • Rendimiento: MySQL es superior en rendimiento.
  • Seguridad: MS Access no tiene soporte para SSL.

MS Access es un intento de un motor de base de datos. Generalmente se usa para cosas muy pequeñas, no tiene utilidad real e importante en el mundo real.

bl4z3r comentado Ene 13, 2016

@migamipe , la definición de una base de datos se basa en las características que soporta y no en las que no soporta.

Te dejo este wiki para que puedas ver que MS Access si es una base de datos que esta trabaja bajo MS Jet Red.

MitsuGami comentado Ene 13, 2016

Si me hablas de definiciones, hasta Derby es una base de datos, pero no sirve más allá que para cosas muy pequeñas. A esto me refiero con que no es una base de datos. Cuando construyes software serio y debes elegir entre motores, nunca tendrás en mente a MS Access, Derby, HSQl, y por el estilo, porque no se consideran base de daos para una aplicación real. A esto me refiero con que MS Access no es una base de datos, porque el proyecto del OP no es algo lo suficientemente pequeño como para usar MS Access.

bl4z3r comentado Ene 13, 2016

@migamipe La selección de un motor de base de datos para una aplicacion depende mucho de los requerimientos funcionales y de ambiente. No tiene sentido colocar un motor de base de datos bestial como, por ejemplo, Oracle Database si solo lo va a usar un solo usuario.
Igual, por lo que puedo suponer en este caso, parece no tener sentido que use MS Access debido a que se aplica a un instituto de sanidad. Pero solo es una suposición.

MitsuGami comentado Ene 14, 2016

Es completamente obvio que una base de datos se utiliza de acuerdo al propósito, eso es cuestión de lógica. Se debe conocer bien los distintos motores, sean SQL o NoSQL para poder elegir uno.

Yo, sinceramente no le veo uso a MS Access. No es portable, no ofrece particionamiento, incluso para cosas pequeñas eligiría MySQL xD. Aunque si eres desarrollador NET, la cosa es diferente porque MS Access se integra bien con NET.

0voto

Gilberto Puntos1210

BUENO BUENO COMO VEO ES ALGO SENCILLO PERO RARO,PRIMERO NO QUE Microsoft Access ES UN SIMULADOR DE BASE DATOS Y TE PREGUNTARAS PORQUE??,YO LA USABA Y SOLO 1 USUARIO PODRIA ENTRAR Y TENIA MAL SEGURIDAD,ASGSNJ ERA UN ASCO EN MI PUNTO,POSIBLEMENTE OTRAS PERSONAS ME CRITIQUEN,PERO BUENO YO TE ACONSEJO MYSql
,oracle, ECT EN VEZ DE ESA.

Y EN LA CLASE DE CONEXION YO TE DIGO QUE USES ESTA ES MEJOR :
Y USA MYSQL,xampp.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.swing.JOptionPane;

public class conexionConBaseDatos {
public static Connection conexion = null;

 public static Connection getConexion() {
     try {
        conexion = null;
        Class.forName("com.mysql.jdbc.Driver");
        conexion =DriverManager.getConnection("jdbc:mysql://127.0.0.1/sistema","root","");
        System.out.println("conexion establecida");
    } catch (ClassNotFoundException | SQLException e) {
        System.out.println("error de conexion");
        JOptionPane.showMessageDialog(null, "error de conexion "+e);
    }
      return conexion;
 }

}


ESPERO QUE TE AYA SERVIDO :)

Por favor, accede o regístrate para responder a esta pregunta.

¿Conoces alguien que puede responder?
¡Comparte esta pregunta!


Actividad Reciente

¿Eres Usuario Apple?

...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta