Android Studio使用JDBC遠程連接mysql的注意事項(附示例)


JDBC為java程序訪問各種類型的關系型數據庫提供了統一的接口,用戶不必針對不同數據庫寫出不同的代碼,但是使用JDBC必須得下載相應的驅動,比如我這里是要連接mysql,於是就到mysql官網去下載x相應驅動 https://dev.mysql.com/downloads/connector/j/

這里我下載解壓得到 mysql-connector-java-5.1.43-bin.jar

在Eclipse中新建java項目只需要Build Path --> Add External Archives把該jar包的路徑添加進來就可以使用。在Android Studio中更是只需要復制粘貼到項目目錄的app\libs下即可,IDE會自動加載。——看似如此。

 

本地Android Studio的配置

我的Android Studio版本是Community Edition2016.2.5,系統是win7 64位。在添加該jar文件后,build出錯。

按照提示,需要在項目最外層的build.gradle文件中的allprojects { ... }區域(具體見代碼下的圖片,之后就不附圖了)內添加下列代碼

    tasks.withType(JavaCompile) {
        sourceCompatibility = '1.7'
        targetCompatibility = '1.7'
    }

這還沒完,此時會提示Error: Unable to find a JDK,起初我懷疑jdk沒添加進環境變量,但是cmd窗口測試無誤,而且Android Studio新建項目也能編譯運行。那么,還是jar包的問題。查了很久后找到了解決方案,看起來是java8的不兼容所致,所以需要全面改為Java7來編譯

 Android Studio2.1.2 Java8環境下引用Java Library編譯出錯

1、在所有module的build.gradle文件中的android { ... }區域中添加

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

就我這個新建的項目,沒有添加module,所以需要修改的文件就只有app\build.gradle

2、在主module的build.gradle文件(也就是app\build.gradle)的android { defaultConfig { ... } }區域中添加

jackOptions {
        enabled true
    }

此時編譯成功了,但是注意,這才是第一步,僅僅只是成功引用了java庫。Android Studio默認是不允許訪問Internet的。

因此需要在app/src/main/AndroidManifest.xml中的<manifest>...</manifest>區域內添加一行

<uses-permission android:name="android.permission.INTERNET"/>

 

遠程mysql的配置

然后我的mysql是安裝在Linux虛擬機(Ubuntu 16.04)上的,默認mysql是禁止遠程連接的,所以在Linux上也要進行配置

首先是要讓mysql支持中文字符,登陸mysql用戶后,輸入命令STATUS;可以看到幾個字符集是這樣的

Server characterset:	latin1
Db     characterset:	latin1
Client characterset:	utf8
Conn.  characterset:	utf8

因此需要用超級用戶權限修改/etc/mysql/my.cnf,添加下列代碼(這里順便綁定了端口為3306,雖然一般默認端口也是3306)

[client]
default-character-set=utf8

[mysqld]
default-storage-engine=INNODB
character-set-server=utf8
collation-server=utf8_general_ci
port=3306

然后重啟mysql,命令如下

$ /etc/init.d/mysql stop
$ /etc/init.d/mysql start

之后再登陸mysql后使用STATUS命令就可以看到字符集全部變成了utf8。

然后mysql默認綁定的IP是127.0.0.1,端口3306,在shell下可以通過shell命令netstat -apn | grep 3306查看端口占用情況,若端口3306對應的第三項(Local Address)是127.0.0.1:3306,那么mysql綁定的就是本地地址,不能遠程連接。

還是用超級用戶權限修改/etc/mysql/my.cnf,添加下列代碼並重啟mysql

bind-address=0.0.0.0

重啟后再用netstat -apn | grep 3306查看第三項就會變成0.0.0.0:3306,那么mysql就支持了遠程連接。

還沒完,雖然mysql賦予了遠程連接的權限,但是mysql用戶並沒有。我這里的mysql用戶名是team,密碼是java123,用root登陸mysql后輸入下列命令

mysql> grant all on *.* to team@'%' identified by 'java123' with grant option;
mysql> flush privileges;

team@'%'代表用戶team支持遠程連接,team@'localhost'則代表用戶team支持本地連接

 

代碼實現

好了,終於可以寫代碼了,於是迫不可待地在MainAcitivity.java的onCreate()方法內部添加下列代碼(先嘗試連接)

        // 1.加載JDBC驅動
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Log.v(TAG, "加載JDBC驅動成功");
        } catch (ClassNotFoundException e) {
            Log.e(TAG, "加載JDBC驅動失敗");
            return;
        }

        // 2.設置好IP/端口/數據庫名/用戶名/密碼等必要的連接信息
        String ip = "192.168.183.134";
        int port = 3306;
        String dbName = "XYZ";
        String url = "jdbc:mysql://" + ip + ":" + port
            + "/" + dbName; // 構建連接mysql的字符串
        String user = "team";
        String password = "java123";

        // 3.連接JDBC
        try {
            Connection conn = DriverManager.getConnection(url, user, password);
            conn.close();
        } catch (SQLException e) {
            Log.e(TAG, "遠程連接失敗!");
            return;
        }

這里使用了andorid.util.Log而不是System.out.println來打印消息,因為可以設置過濾符,通過TAG、日志級別等信息來篩選出特定的日志

這里我就是通過TAG來篩選,也可以通過Message和Package來篩選,並且支持正則表達式,程序運行時會有大量日志混雜在一起,所以使用Log而不是System.out來打印消息更好。

於是,通過日志過濾符篩選,可以發現連接失敗了。

這個問題折磨了我一天多,參考了很多網上的代碼,和我的基本無異,而且也copy過來測試過都不行,最后在stackoverflow上找到了解答

https://stackoverflow.com/questions/12233145/connecting-to-mysql-from-android-with-jdbchttps://stackoverflow.com/questions/12233145/connecting-to-mysql-from-android-with-jdbc

mysql的連接必須在異步任務類中,也就是說必須新建線程來連接mysql,而不能在主線程中執行代碼。

        final Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                // 反復嘗試連接,直到連接成功后退出循環
                while (!Thread.interrupted()) {
                    try {
                        Thread.sleep(100);  // 每隔0.1秒嘗試連接
                    } catch (InterruptedException e) {
                        Log.e(TAG, e.toString());
                    }

                    // 2.設置好IP/端口/數據庫名/用戶名/密碼等必要的連接信息
                    String ip = "192.168.183.134";
                    int port = 3306;
                    String dbName = "XYZ";
                    String url = "jdbc:mysql://" + ip + ":" + port
                            + "/" + dbName; // 構建連接mysql的字符串
                    String user = "team";
                    String password = "java123";

                    // 3.連接JDBC
                    try {
                        Connection conn = DriverManager.getConnection(url, user, password);
                        Log.i(TAG, "遠程連接成功!");
                        conn.close();
                        return;
                    } catch (SQLException e) {
                        Log.e(TAG, "遠程連接失敗!");
                    }
                }
            }
        });
        thread.start();

成功了,總算可以繼續下一步,向遠程連接的mysql發送命令了,將上述代碼稍作修改

                    // 3.連接JDBC
                    Connection conn = null;
                    try {
                        conn = DriverManager.getConnection(url, user, password);
                        Log.i(TAG, "遠程連接成功!");
                    } catch (SQLException e) {
                        Log.e(TAG, "遠程連接失敗!");
                    }

                    if (conn != null) {
                        String sql = "SELECT * FROM pokemon";

                        try {
                            // 創建用來執行sql語句的對象
                            java.sql.Statement statement = conn.createStatement();
                            // 執行sql查詢語句並獲取查詢信息
                            ResultSet rSet = statement.executeQuery(sql);
                            // 迭代打印出查詢信息
                            Log.i(TAG, "寶可夢列表");
                            Log.i(TAG, "ID\tName\tAttr1\tAttr2");
                            while (rSet.next()) {
                                Log.i(TAG, rSet.getString("id") + "\t" + rSet.getString("name")
                                    + "\t" + rSet.getString("attr1") + "\t" + rSet.getString("attr2"));
                            }
                        } catch (SQLException e) {
                            Log.e(TAG, "createStatement error");
                        }

                        try {
                            conn.close();
                        } catch (SQLException e) {
                            Log.e(TAG, "關閉連接失敗");
                        }

懶得仔細研究java格式化字符串,直接把結果打印出來了,這里只用到了執行查詢語句的executeQuery,返回結果到一組迭代對象。

而execute則可以執行任何sql語句,更多API可以參考JDBC官方教程 http://docs.oracle.com/javase/tutorial/jdbc/basics/index.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM