Establish pooled connection to MySQL in android

2019-05-24 19:36发布

I need to access a MySQL db from my android app. Now all the work is done through

DriverManager.getConnection(url);

and so on. But I have to access the db from multiple threads, so I have to use connection pooling.

Question 1. Is

com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();

the right way of creating the data source?

Question 2. If I write the previous line of code, my app compiles and installs on the device (not emulator) fine, but I get a weird

java.lang.NoClassDefFoundError: com.mysql.jdbc.jdbc2.optional.MysqlDataSource`

, that I can't catch with a try/catch handler:

try
{
com.mysql.jdbc.jdbc2.optional.MysqlDataSource a = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();
}
catch (Exception e)
{
I don't get here. The app just crashes, as if I had no try/catch block.
}

Question 3. I copied mysql-connector-java-5.1.20-bin.jar to the device and wrote the following code:

try
{
final String str = Environment.getExternalStorageState();
final File sd = getActivity().getExternalFilesDir(null);
final File file = new File(sd, "mysql-connector-java-5.1.20-bin.jar");

boolean b = file.exists();

final URLClassLoader cl = URLClassLoader.newInstance(new URL[] {file.toURI().toURL()} );
cl.loadClass("com.mysql.jdbc.jdbc2.optional.MysqlDataSource"); //$NON-NLS-1$
}

catch (Exception e)
{
new AlertDialog.Builder(getActivity())
.setMessage(ObjectConverter.throwable2String(e))
.show();
}

The file is found but

cl.loadClass()

fails with

java.lang.NullPointerException
at java.net.URLClassLoader.getPermissions(URLClassLoader.java:614)
at java.security.SecureClassLoader.getPD(SecureClassLoader.java:140)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:93)
at java.net.URLClassLoader.access$600(URLClassLoader.java:55)
at java.net.URLClassLoader$URLJarHandler.createClass(URLClassLoader.java:364)
at java.net.URLClassLoader$URLJarHandler.findClass(URLClassLoader.java:303)
at java.net.URLClassLoader.findClass(URLClassLoader.java:748)
at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
at ru.mypkg.myapp.func(myapp.java:367)
at android.view.View.performClick(View.java:3511)
at android.view.View$PerformClick.run(View.java:14110)
at android.os.Handler.handleCallback(Handler.java:605)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4424)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

Any help greatly appreciated.

1条回答
Root(大扎)
2楼-- · 2019-05-24 20:21

This question is 6 years old and Mark is correct that, in almost every scenario you can think of, JDBC on Android is about as sensible as trying to use a toaster in the bath. However, sometimes we do things because we can and not because we necessarily should, and today I had a justifiable reason to want to do this (for a specific very niche app running in an unusual environment), which is how I found this question.

Addressing the NoClassDefFoundError first, the reason it isn't caught by the catch block is because it's an Error not an Exception. Both Error and Exception inherit from Throwable, so you could catch that instead:

catch (Throwable t)
{
    // This will catch NoClassDefFoundError
}

I believe that it's not MySqlDataSource that it can't find, but one of the classes or interfaces that it depends on - in my case it was javax.naming.Referenceable. Android doesn't provide the javax.naming package so trying to use the pooling features of the Connector/J JDBC driver for MySQL isn't going to get you very far (you could try to provide the missing dependencies but that road likely leads to madness).

Instead you'll probably have more luck with a third-party connection pool implementation. There are various Java libraries for doing this. Some of them will work on Android. One that I have verified does work is HikariCP. There are instructions for configuring it here and, specifically for MySQL, here.

查看更多
登录 后发表回答