2010-06-10 22 views
15

Come è possibile aggiungere driver JDBC in fase di esecuzione a Jython? L'utilizzo di CLASSPATH funziona, ma l'utilizzo di sys.path non funziona con zxJDBC anche se la classe viene importata correttamente e può essere modificata dal prompt dell'interprete Jython.JYthon CLASSPATH, driver sys.path e JDBC

Perché questo lavoro:

$ CLASSPATH=/tmp/jtds\-1.2.5.jar ./jython 
*sys-package-mgr*: processing new jar, '/private/tmp/jtds-1.2.5.jar' 
Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from java.lang import Class 
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver') 
<type 'net.sourceforge.jtds.jdbc.Driver'> 

Ma questo non lo fa?

$ ./jython 

Jython 2.5.1 (Release_2_5_1:6813, Sep 26 2009, 13:47:54) 
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_20 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import sys 
>>> sys.path.extend(['/tmp/jtds-1.2.5.jar']) 
>>> from java.lang import Class 
>>> Class.forName('net.sourceforge.jtds.jdbc.Driver') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
     at java.net.URLClassLoader$1.run(URLClassLoader.java:202) 
     at java.security.AccessController.doPrivileged(Native Method) 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:307) 
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:248) 
     at java.lang.Class.forName0(Native Method) 
     at java.lang.Class.forName(Class.java:169) 
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
     at java.lang.reflect.Method.invoke(Method.java:597) 

java.lang.ClassNotFoundException: java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver 
>>> sys.path 
['', '/home/me/pkg/jython2.5.1/Lib/site-packages/distribute-0.6.13-py2.5.egg', '/home/me/pkg/jython2.5.1/Lib', '__classpath__', '__pyclasspath__/', '/home/me/pkg/jython2.5.1/Lib/site-packages', '/home/me/pkg/jython2.5.1/Lib/site-packages/setuptools-0.6c11-py2.5.egg-info', '/tmp/jtds-1.2.5.jar'] 
>>> import net.sourceforge.jtds.jdbc.Driver as Driver 
>>> drv = Driver() 
>>> drv 
jTDS 1.2.5 

Ha qualcosa a che fare con il classloader?

risposta

5

La soluzione è complicata, ma è tutto spiegato here.

+1

Sembra che il motivo sia dovuto al fatto che JDBC DriverManager utilizza solo i driver caricati utilizzando il classloader di sistema, anche se ciò che è registrato è un'istanza del driver, non una classe. Grazie per il link. Per qualsiasi altra lettura, http://stackoverflow.com/questions/288828/how-to-use-a-jdbc-driver-from-an-arbitrary-location e http://www.kfu.com/~nsayer/ Java/dyn-jdbc.html potrebbe essere utile. – lmz

+4

-1 Dead link, quindi la soluzione è andata persa. – brice

+0

Il collegamento funziona correttamente. – hhhhhh

19

Sembra che anche il collegamento aggiornato non funzioni più (almeno con jython-2.5.3b3).

Ecco una versione funzionante:

def importJar(jarFile): 
    ''' 
    import a jar at runtime (needed for JDBC [Class.forName]) 

    adapted from http://forum.java.sun.com/thread.jspa?threadID=300557 
    Author: SG Langer Jan 2007 translated the above Java to Jython 
    Author: [email protected] simplified and updated for jython-2.5.3b3 

    >>> importJar('jars/jtds-1.2.5.jar') 
    >>> import java.lang.Class 
    >>> java.lang.Class.forName('net.sourceforge.jtds.jdbc.Driver') 
    <type 'net.sourceforge.jtds.jdbc.Driver'> 
    ''' 
    from java.net import URL, URLClassLoader 
    from java.lang import ClassLoader 
    from java.io import File 
    m = URLClassLoader.getDeclaredMethod("addURL", [URL]) 
    m.accessible = 1 
    m.invoke(ClassLoader.getSystemClassLoader(), [File(jarFile).toURL()]) 

if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

tengo this Gist aggiornato con la mia versione di produzione.

+0

Il codice dal collegamento aggiornato sopra non ha funzionato, ma questo ha fatto! (dovevo eliminare i commenti) – bobfet1

+0

Il codice nel libro Jython 1.0 non funzionava nemmeno per me su Jython 2.5.2, ma importJar sì. Grazie ! – David

Problemi correlati