Connect Android App to Bluemix db2 database using JDBC (NoClassDefFoundError:)

Connect Android App to Bluemix db2 database using JDBC (NoClassDefFoundError:)

首先:我在 Java 方面有一些经验,但这是我第一次创建 Android-App。 我正在使用 Bluemix IoT-Foundation-Service 并获得了一个 Bluemix-DB2-SQL-Database。 (我的 RasPi2 正在收集一些传感器数据,通过 MQTT 和订阅此数据的 bluemix 上的应用程序 运行ning 发布它们,将它们存储到 DB2 数据库中)。

现在我想编写一个 Android 应用程序,它连接到我的数据库并执行一些数据库操作。我从一个简单的应用程序开始。只是一个在我的 DB2-TodoList-Table 上添加内容的按钮。

代码:

import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import java.sql.*;
public class MainActivity extends AppCompatActivity {

static Connection       con;
static Statement        stmt;
static Statement        stmt1;
static DatabaseMetaData dmd;


private static String user = "user*****";
private static String password = "L***********";
private static String url = "jdbc:db2://*.**.*****:50001/SQLDB";


public void connect(){
    java.util.Properties properties = new java.util.Properties();

    properties.put("user", user);
    properties.put("password", password);
    properties.put("sslConnection", "true");

    try {
        Class.forName("com.ibm.db2.jcc.DB2Driver");
    con = DriverManager.getConnection(url, properties);
    stmt = con.createStatement();

    } catch (ClassNotFoundException e) {
       // e.printStackTrace();
    } catch (SQLException e) {
      //  e.printStackTrace();
    }
}
public void close() throws SQLException, ClassNotFoundException{
    stmt.close();
    con.close();
}

public static void addSomethingToMyToDoList(int ID, String something) throws SQLException{
    if(con != null)
        stmt.executeUpdate("INSERT INTO TODOLIST VALUES (" + ID + " , '" + something +"')");
    con.commit();
}

public void addSomethingToDatabase(View v){
    connect();
    int sampleID = 1233;
    try {
        addSomethingToMyToDoList(sampleID, "testTest");
         close();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
}

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.menu_main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}
}

我将 db2jcc.jar 拖放到 /app/libs 文件夹中,然后右键单击 + 添加为库

我使用 Android Studio

我读到 db2jcc.jar 不适用于 jdk 1.8,这就是我安装 jdk 1.7 的原因(文件 -> 项目结构 -> SDK 位置 -> 已更改JDK 位置到我的 jdk1.7.0 目录)

build.gradle 文件包含:

defaultConfig {
    [...]
    multiDexEnabled true
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile files('libs/db2jcc.jar')
testCompile 'junit:junit:4.12'
compile 'com.android.support:design:23.1.1'
compile 'com.android.support:multidex:1.0.1'
compile 'com.android.support:appcompat-v7:23.1.1'
}

当我 运行 我的应用程序(在 AVD 上)并单击按钮时,我的应用程序崩溃了,我收到此消息:

Caused by: java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2SimpleDataSource

完整错误日志:

FATAL EXCEPTION: main Process: com.example.egebert.datanbank, PID: 7125 java.lang.IllegalStateException: Could not execute method for android:onClick at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:275) at android.view.View.performClick(View.java:5198) at android.view.View$PerformClick.run(View.java:21147) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270) at android.view.View.performClick(View.java:5198)  at android.view.View$PerformClick.run(View.java:21147)  at android.os.Handler.handleCallback(Handler.java:739)  at android.os.Handler.dispatchMessage(Handler.java:95)  at android.os.Looper.loop(Looper.java:148)  at android.app.ActivityThread.main(ActivityThread.java:5417)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)  Caused by: java.lang.NoClassDefFoundError: com.ibm.db2.jcc.DB2SimpleDataSource at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.am.GlobalProperties.d(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.a(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.c(Unknown Source) at com.ibm.db2.jcc.am.GlobalProperties.a(Unknown Source) at com.ibm.db2.jcc.am.hb.j(Unknown Source) at com.ibm.db2.jcc.am.hb.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.DB2BaseDataSource.class$(Unknown Source) at com.ibm.db2.jcc.DB2BaseDataSource.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.ibm.db2.jcc.DB2Driver.class$(Unknown Source) at com.ibm.db2.jcc.DB2Driver.(Unknown Source) at java.lang.Class.classForName(Native Method) at java.lang.Class.forName(Class.java:324) at java.lang.Class.forName(Class.java:285) at com.example.egebert.datanbank.MainActivity.connect(MainActivity.java:40) at com.example.egebert.datanbank.MainActivity.addSomethingToDatabase(MainActivity.java:78) at java.lang.reflect.Method.invoke(Native Method)  at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:270)  at android.view.View.performClick(View.java:5198)  at android.view.View$PerformClick.run(View.java:21147)  at android.os.Handler.handleCallback(Handler.java:739)  at android.os.Handler.dispatchMessage(Handler.java:95)  at android.os.Looper.loop(Looper.java:148)  at android.app.ActivityThread.main(ActivityThread.java:5417)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)

我试过了

Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();

而不是

Class.forName("com.ibm.db2.jcc.DB2Driver");

也是。

没有办法让 JDBC-db2Driver 在 Android 上工作吗? 刚刚发现 Whosebug 问题告诉我,您无法使用 android 连接到 bluemix-db2-server。这是正确的吗?或者有没有办法修复 NoClassDefFoundError?

谢谢你

错误很明显,您的应用程序找不到 db2 模块。检查您是否将这些模块正确导入到您的应用程序库中,并且添加到 lib 中的驱动程序是否提供了您正在使用的数据源。

无论如何,出于以下几个原因,我会避免让您的应用程序直接连接到外部数据库:

  • 数据库连接通常是有限的,并且为每个应用程序实例使用它们会使数据库实例快速失去可用连接,特别是如果数据库交互不是很短并且连接没有正确释放
  • 便携式设备的网络连接不稳定,您可能会在 运行 数据库操作时失去连接

通常更好的解决方案应该是添加一个集成层(如 Web 服务),管理所有数据库交互(包括数据库连接),并为应用程序集成公开一些端点。