• 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中更是只需要复制粘贴到项目目录的applibs下即可,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,所以需要修改的文件就只有appuild.gradle

    2、在主module的build.gradle文件(也就是appuild.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	Name	Attr1	Attr2");
                                while (rSet.next()) {
                                    Log.i(TAG, rSet.getString("id") + "	" + rSet.getString("name")
                                        + "	" + rSet.getString("attr1") + "	" + 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

  • 相关阅读:
    学习算法和刷题的思路指南
    提交包到iTunes Connect时构建版本“正在处理”后直接消失的问题
    对网络通讯的一些学习和总结
    iOS开发 dispatch_block_t 简单的实现不带参数的回调函数
    app刚开始启动时(即:appdelegate文件中)可以写的几个功能
    拷贝项目时,自己总结的一些小事项
    iOS开发中遇到的一些问题以及解决办法总结
    宝库~iOS开发笔试题
    GCD 之线程死锁
    iOS开发之旅之懒加载
  • 原文地址:https://www.cnblogs.com/Harley-Quinn/p/7389681.html
Copyright © 2020-2023  润新知