2008-11-14 18 views
17

Necesito probar una conexión JDBC a una base de datos. El código Java para hacer eso debe ser tan simple como:Cómo utilizar un controlador JDBC desde una ubicación arbitraria

DriverManager.getConnection("jdbc connection URL", "username", "password"); 

El gestor de controladores será buscar el apropiado el controlador para la URL de conexión dado. Sin embargo, necesito poder cargar el controlador JDBC (jar) en tiempo de ejecución. Es decir, no tengo el controlador JDBC en el classpath de la aplicación java que ejecuta el fragmento de código anterior.

Para que pueda cargar el controlador que utiliza este código, por ejemplo:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"jar URL"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("jdbc driver class name", true, classLoader).newInstance(); 

Pero entonces el gestor de controladores todavía no voy a recogerlo ya que no puedo decirle qué cargador de clases para su uso. Intenté configurar el cargador de clases de contexto del subproceso actual y todavía no funciona.

¿Alguien tiene alguna idea sobre la mejor manera de lograrlo?

+0

¿Hay alguna buena razón por la cual no tiene el controlador en el classpath? –

+0

Sí. La aplicación se puede conectar a muchas bases de datos. Además, no puedo agrupar todos los controladores por razones de licencia. Lo que quiero lograr es un diálogo simple para que el usuario cargue el contenedor mientras se ejecuta la aplicación. – SaM

+0

Ahí estaba pensando como un desarrollador de servidor de nuevo ... :) –

Respuesta

17

A partir del artículo Pick your JDBC driver at runtime; Voy a publicar el código aquí como referencia.

La idea es engañar al administrador del controlador para que piense que el controlador se cargó desde el cargador de clases del sistema. Para ello se utiliza esta clase:

public class DelegatingDriver implements Driver 
{ 
    private final Driver driver; 

    public DelegatingDriver(Driver driver) 
    { 
     if (driver == null) 
     { 
      throw new IllegalArgumentException("Driver must not be null."); 
     } 
     this.driver = driver; 
    } 

    public Connection connect(String url, Properties info) throws SQLException 
    { 
     return driver.connect(url, info); 
    } 

    public boolean acceptsURL(String url) throws SQLException 
    { 
     return driver.acceptsURL(url); 
    } 

    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException 
    { 
     return driver.getPropertyInfo(url, info); 
    } 

    public int getMajorVersion() 
    { 
     return driver.getMajorVersion(); 
    } 

    public int getMinorVersion() 
    { 
     return driver.getMinorVersion(); 
    } 

    public boolean jdbcCompliant() 
    { 
     return driver.jdbcCompliant(); 
    } 
} 

De esta manera el conductor se registra es de tipo DelegatingDriver que se carga con el cargador de clases del sistema. Ahora solo tiene que cargar el controlador que realmente desea usar utilizando el cargador de clases que desee. Por ejemplo:

URLClassLoader classLoader = new URLClassLoader(new URL[]{"path to my jdbc driver jar"}, this.getClass().getClassLoader()); 
Driver driver = (Driver) Class.forName("org.postgresql.Driver", true, classLoader).newInstance(); 
DriverManager.registerDriver(new DelegatingDriver(driver)); // register using the Delegating Driver 

DriverManager.getDriver("jdbc:postgresql://host/db"); // checks that the driver is found 
5

El problema es DriverManager realiza "tareas utilizando la clase instancia del cargador del llamador inmediato". Ver la Pauta 6-3 de Secure Coding Guidelines for the Java Programming Language, version 2.0. El cargador de clases del sistema no es de ninguna manera especial en este caso.

Solo por las patadas, escribí un blog entry sobre este tema hace un tiempo. Mi solución, aunque más complicada que Nick Sayer's solution, es más completa e incluso funciona desde código que no es de confianza. También se debe tener en cuenta URLClassLoader.newInstance sobre new URLClassLoader.

Cuestiones relacionadas