首页 > 解决方案 > Android 中的 JDBC 连接问题

问题描述

我按照youtube 上的教程制作了一个带有数据库的列表应用程序。现在我得到错误:

为 JDBC 引发了异常。

这是我的代码:

package com.example.jopri.databaseconnectie;

import android.content.AsyncQueryHandler;
import android.content.Context;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

ItemAdapter itemAdapter;
Context thisContext;
ListView myListView;
TextView progressTextView;
Map<String, Double> fruitsMap = new LinkedHashMap<String, Double>();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Resources res = getResources();
    myListView = (ListView) findViewById(R.id.myListView);
    progressTextView = (TextView) findViewById(R.id.progressTextView);
    thisContext = this;

    progressTextView.setText("");
    Button btn = (Button) findViewById(R.id.getDataButton);
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v){
            GetData retrieveData = new GetData();
            retrieveData.execute("");
        }
    });

}

private class GetData extends AsyncTask<String, String, String> {

    String msg = "";

    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";

    static final String DB_URL = "jdbc:mysql://" +
            DbStrings.DATABASE_URL + "/" +
            DbStrings.DATABASE_NAME;

    protected void onPreExecute() {
        progressTextView.setText("Connecting to database...");
    }

    @Override
    protected String doInBackground(String... params) {

        Connection conn = null;
        Statement stmt = null;

        try {
            Class.forName(JDBC_DRIVER);
            conn = DriverManager.getConnection(DB_URL, DbStrings.USERNAME, DbStrings.PASSWORD);

            stmt = conn.createStatement();
            String sql = "SELECT * FROM fruit";
            ResultSet rs = stmt.executeQuery(sql);

            while (rs.next()) {
                String soort = rs.getString("soort");
                double prijs = rs.getDouble("prijs");

                fruitsMap.put(soort, prijs);
            }

            msg = "Process complete";

            rs.close();
            stmt.close();
            conn.close();

        } catch (SQLException connError) {
            msg = "An exception was thrown for JDBC";
            connError.printStackTrace();
        } catch (ClassNotFoundException e) {
            msg = "A class not found exception was thrown.";
            e.printStackTrace();
        } finally {

            try {
                if (stmt != null) {
                    stmt.close();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                if (conn != null) {
                    conn.close();
                }

            } catch (SQLException e) {
                e.printStackTrace();
            }

        }

        return null;
    }

    @Override
    protected void onPostExecute(String msg) {
        progressTextView.setText(this.msg);

        if(fruitsMap.size() > 0) {
            itemAdapter = new ItemAdapter(thisContext, fruitsMap);
            myListView.setAdapter(itemAdapter);
        }
    }
}

} // END

连接器:

package com.example.jopri.databaseconnectie;

import java.net.URL;

public class DbStrings {

static final String DATABASE_URL = "127.0.0.1:3306";
static final String DATABASE_NAME = "proef";
static final String USERNAME = "root";
static final String PASSWORD = "password";
}

物品适配器:

package com.example.jopri.databaseconnectie;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
 import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
 import java.util.Map;

 public class ItemAdapter extends BaseAdapter {


LayoutInflater mInflator;
Map<String, Double> map;
List<String> soort;
List<Double> prijs;

public ItemAdapter(Context c, Map m) {
    mInflator = (LayoutInflater)     c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    map = m;
    soort = new ArrayList<String>(map.keySet());
    prijs = new ArrayList<Double>(map.values());

};

@Override
public int getCount() {
    return map.size();
}

@Override
public Object getItem(int position) {
    return soort.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = mInflator.inflate(R.layout.item_layout, null);
    TextView nameTextView = (TextView) v.findViewById(R.id.nameTextView);
    TextView priceTextView = (TextView) v.findViewById(R.id.priceTextView);

    nameTextView.setText(soort.get(position));
    priceTextView.setText("€" + prijs.get(position).toString());

    return v;
}

}

标签: javaandroid

解决方案


static final String DATABASE_URL = "127.0.0.1:3306";

这条线意味着您正在 Android 设备本身上运行 MySQL 服务器,这对我来说似乎不太可能。如果您再次观看视频,他从未使用过 localhost/127.0.0.1。

此 URL 应该是可在您的网络中解析的远程 IP/主机名(理想情况下,应该通过 WiFi 和移动设备工作)

此外,通过这样做,您会将您的数据库密码暴露给任何可以访问您的应用程序/代码的人,因为它只是内存中的一个普通字符串。因此,在现实世界的环境中,您实际上会使用基于 HTTP 的 API,它可以更安全地隐藏数据库凭据并将其存储在一个位置,而不是将该信息复制到一堆移动设备上(如果您发布您的应用程序)供他人使用)。

如果您想要的只是一个带有列表视图的数据库,请从 SQLite 开始,它作为 Android SDK 的一部分嵌入并作为库提供


推荐阅读