【问题标题】:Establish pooled connection to MySQL in android在android中建立与MySQL的池连接
【发布时间】:2012-05-12 16:31:31
【问题描述】:

我需要从我的 android 应用程序访问 MySQL 数据库。现在所有的工作都通过

DriverManager.getConnection(url);

等等。但是我必须从多个线程访问数据库,所以我必须使用连接池。

问题 1. 是

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

创建数据源的正确方法?

问题 2. 如果我编写上一行代码,我的应用程序可以编译并安装在设备(不是模拟器)上,但我觉得很奇怪

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

,我无法使用 try/catch 处理程序捕获:

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.
}

问题3,我将mysql-connector-java-5.1.20-bin.jar复制到设备中,写了如下代码:

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();
}

文件找到了,但是

cl.loadClass()

失败

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)

非常感谢任何帮助。

【问题讨论】:

  • 请将您的数据库包装在 Web 服务中,并在 Android 中使用该服务。 JDBC 不适用于您在移动设备上发现的那种不可靠的网络连接。
  • 非常感谢您的回答!我已经考虑过使用 HTML 来处理请求和响应,但我想目前这是不可能的,因为我们没有时间这样做。如果我们谈论移动设备,为什么网络连接不可靠? JDBC 有什么问题使它不适合此类任务?而且,最重要的是,我能否以某种方式从 Android 建立到 MySQL 的池连接?
  • “如果我们谈论移动设备,为什么网络连接不可靠?” ——移动设备是移动的。用户脱离 WiFi 并故障转移到移动数据,或再次翻转。用户蜿蜒进入移动数据信号较差的地方。等等。 “JDBC 有什么问题使它不适合此类任务?” -- JDBC 大约有 15 年的历史,是围绕稳定的 LAN 连接设计的(我也不会在 Internet 上使用它)。 “我能以某种方式从 Android 建立到 MySQL 的池连接吗?” -- 我不知道,如果他们为我工作,我会解雇任何尝试过的人。
  • 当然是这样的。但是在我正在开发的应用程序的上下文中,它有点不同。我们组织了一个 WiFi 网络,并声明我们的应用程序(只是一个更大的综合体的一部分)仅在它存在的情况下工作(并且客户同意这一点)。我是否正确地将数据库包装在 Web 服务中?您的意思是应用程序以 HTML 格式发送请求并以相同的方式获得响应?
  • “我们组织了一个 WiFi 网络并声明我们的应用程序(只是一个更大的综合体的一部分)仅在它存在的情况下工作(并且客户同意这一点)。” ——嗯,好的。 “你的意思是应用程序以 HTML 格式发送请求并以相同的方式获得响应?” -- 不,我的意思是 Web 服务 -- en.wikipedia.org/wiki/Web_service REST,以及在较小程度上的 SOA,在 Android 上运行得最好,仅仅是因为 Android 缺少内置的 SOAP 端点。

标签: android mysql connection-pooling


【解决方案1】:

这个问题已有 6 年历史,Mark 是正确的,几乎在您能想到的所有场景中,Android 上的 JDBC 都与尝试在浴缸中使用烤面包机一样明智。然而,有时我们做事是因为我们可以而不是因为我们必须这样做,今天我有一个正当的理由想要这样做(对于在不寻常的环境中运行的特定非常小众的应用程序),这就是我发现这个问题的方式。

首先寻址NoClassDefFoundError,它没有被catch 块捕获的原因是因为它是Error 而不是ExceptionErrorException 都继承自 Throwable,所以你可以抓住它:

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

我相信它找不到的不是MySqlDataSource,而是它所依赖的类或接口之一——在我的例子中是javax.naming.Referenceable。 Android 不提供 javax.naming 包,因此尝试使用 MySQL 的 Connector/J JDBC 驱动程序的池功能不会让您走得太远(您可以尝试提供缺少的依赖项,但这条路可能会导致疯狂)。

相反,您可能会更幸运地使用第三方连接池实现。有各种 Java 库可以做到这一点。其中一些将在 Android 上运行。我已经验证确实有效的一个是HikariCP。有配置它的说明here,特别是对于 MySQL,here

【讨论】:

  • 感谢您分享您对该主题的方法和想法。我认为这对于那些不想“带着烤面包机在浴缸里游泳”的人来说真的很有价值:)。附言我希望今天我能够理解为什么 NoClassDefFound 没有被抓住:)。
  • 你能告诉我你是如何让HIkariCP在android上工作的吗?我遇到了 class-not-found 和其他依赖问题。我正在尝试在要导入 Android Studio 项目的 my-jar 中使用它。
  • @sharonooo 找不到哪些课程?我将 Hikari 依赖项添加到我的 Gradle 文件中,并将 MySQL 连接器 JAR 文件包含在我的项目中。我的 Gradle 依赖项中也有 slf4j-android,我认为这是由于 Hikari。
  • @DanDyer 我得到:Caused by: java.lang.ClassNotFoundException: Class io.prometheus.client.Collector not found 我创建了一个包含所有依赖项的 JAR,我正在使用 gradle 将此 jar 导入到 android studio。我正在尝试将 HakiriCP 与 H2 数据库一起使用。我注意到一件事:HakiriCP 有 provided 依赖项,它没有添加到类路径中,这是导致错误的原因。
  • 还尝试将 io.prometheus 导入 androids 项目 gradle 文件。还有另一个错误:Could not find class 'javax.naming.InitialContext', referenced from method com.zaxxer.hikari.HikariConfig.getObjectOrPerformJndiLookup
猜你喜欢
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 2012-11-02
  • 2012-03-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多