【Android 远程数据库操作】

news2024/12/26 23:14:26

按正常情况下,前端不应该直接进行远程数据库操作,这不是一个明智的方式,应该是后端提供对应接口来处理,奈何公司各方面原因需要前端这样做。

对此,我对远程数据库操作做了总结,便于自己复盘,同时,也分享给有需要的朋友们。

0、下载jdbc库

下载mysql官网:https://dev.mysql.com/downloads/connector/j/,按图片步骤下载所需jdbc的库
在这里插入图片描述在这里插入图片描述

1、添加jdbc驱动依赖包

在Android studio的项目工程app-bulid.grade添加依赖:implementation files(‘libs/mysql-connector-java-5.1.48.jar’)或implementation 'mysql:mysql-connector-java:5.1.48’这两种方式
在这里插入图片描述

2、数据库连接操作

			private String DB_URL = "jdbc:mysql://127.0.0.1:3306/远程数据库名";//换成远程地址
   		    private String USER = "admin";//账号
   		    private String PASS = "123456";	//密码
    		
			// Step 1: 加载 JDBC driver
            Class.forName("com.mysql.jdbc.Driver");//mysql高版本这里:com.mysql.cj.jdbc.Driver

            // Step 2: 打开连接
            Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);

3、执行数据库语句操作,进行相关业务处理

			String sql = "select name, age, sex from User";// sql语句
			Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            while (rs.next() && !isStopped) {
				// todo 相应业务处理
			}

4、数据库关闭

			// 操作完毕,数据库关闭
			rs.close();
            statement.close();
            connection.close();

5、完整代码

远程数据库操作工具类DatabaseAccessUtil,由于是耗时动作,需要在线程处理。

public class DatabaseAccessUtil {

    private static final String TAG = "F100 DatabaseAccess";

    private String DB_URL = "jdbc:mysql://127.0.0.1:3306/数据库名";
    private String USER = "admin";
    private String PASS = "123456";

    private static DatabaseAccessUtil instance;
    private ExecutorService executorService;
    private volatile boolean isStopped = false;
    private Future<?> currentTask = null; // 用于保存当前的任务

    private ProgressDialogUtil progressDialogUtil;
    private Handler mainHandler;

    private DatabaseAccessUtil() {
        this.executorService = Executors.newSingleThreadExecutor();
        mainHandler = new Handler(Looper.getMainLooper());
    }

    public static synchronized DatabaseAccessUtil getInstance() {
        if (instance == null) {
            instance = new DatabaseAccessUtil();
        }
        return instance;
    }

    public void start(Context context) {
        stop();
        isStopped = false;
        if (executorService == null || executorService.isShutdown()) {
            executorService = Executors.newSingleThreadExecutor();
        }

        if (!isStopped && !executorService.isShutdown()) {
            currentTask = executorService.submit(() -> downloadData(context));
        }
    }

    public void stop() {
        isStopped = true;
        if (currentTask != null) {
            currentTask.cancel(true); // 尝试取消当前任务
            currentTask = null;
            executorService.shutdownNow(); // 停止执行器服务
        }
    }

    private void showProgressDialog(Context context) {
        mainHandler.post(() -> {
            if (progressDialogUtil == null) {
                progressDialogUtil = new ProgressDialogUtil(context);
                progressDialogUtil.setOnCancelListener(() -> {
                    stop();
                });
            }
            progressDialogUtil.showProgressDialog();
        });
    }

    // 查询表的总数量
    private int getTotalCountFromDB(Connection connection) throws SQLException {
        String sql = "select count(*) from User";
        Statement statement = connection.createStatement();
        ResultSet rs = statement.executeQuery(sql);
        rs.next();
        int totalCount = rs.getInt(1);
        rs.close();
        statement.close();
        return totalCount;
    }

    // 下载数据(相应业务处理)
    private void downloadData(Context context) {
        if (isStopped) return;

        try {
            String sql = "select name, age, sex from User";
            // Step 1: Register JDBC driver
            Class.forName("com.mysql.jdbc.Driver");//mysql高版本这里:com.mysql.cj.jdbc.Driver

            // Step 2: Open a connection
            Connection connection = DriverManager.getConnection(DB_URL, USER, PASS);

            // Step 3: Execute a query
            int totalCount = getTotalCountFromDB(connection);
            if (totalCount == 0) {
                connection.close();
                EventBus.getDefault().post(new CommonEvent(EventCode.FLAG_NO_DATA));
                return;
            }

            // 显示进度条
            // todo showProgressDialog(context);

            // 执行sql 业务逻辑
            Statement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sql);

            int count = 0;
            while (rs.next() && !isStopped) {
                // 进度条更新
                count++;
                int progress = (count * 100) / totalCount;
                updateProgress(progress);

                // Retrieve by column name
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String sex = rs.getString("sex");

                // todo 业务逻辑处理

            }

            // 关闭
            rs.close();
            statement.close();
            connection.close();

            // 主线程回调, 这里我使用订阅
            EventBus.getDefault().post(new CommonEvent(EventCode.FLAG_SUCCESS));
        } catch (Exception e) {
            // 主线程回调
            EventBus.getDefault().post(new CommonEvent(EventCode.FLAG_FAIL));
        } finally {
            // 进度条关闭
            mainHandler.post(() -> {
                if (progressDialogUtil != null) progressDialogUtil.dismissProgressDialog();
            });
        }
    }

    // 进度条更新
    private void updateProgress(int progress) {
        mainHandler.post(() -> {
            if (progressDialogUtil != null) {
                progressDialogUtil.updateProgress(progress);
            }
        });
    }

}

进度条ProgressDialogUtil,布局:一个进度条+进度条进度+取消按钮,【取消】按钮是1分钟后可点击。代码如下:

public class ProgressDialogUtil {

    private final long DELAY_TIME = 1 * 60 * 1000;//2分钟  2 * 60 * 1000

    private Dialog progressDialog;
    private ProgressBar progressBar;
    private TextView tvProgress;
    private Button btnCancel;
    private Handler handler;
    private boolean cancelEnabled = false;

    public ProgressDialogUtil(Context context) {
        progressDialog = new Dialog(context, R.style.CustomProgressDialog);
        progressDialog.setContentView(R.layout.dialog_progress);
        progressDialog.setCancelable(false);

        progressBar = progressDialog.findViewById(R.id.progressBar);
        tvProgress = progressDialog.findViewById(R.id.tvProgress);
        btnCancel = progressDialog.findViewById(R.id.btnCancel);
        btnCancel.setEnabled(false);

        handler = new Handler();
    }

    public void showProgressDialog() {
        Window window = progressDialog.getWindow();
        if (window != null) {
            WindowManager.LayoutParams params = window.getAttributes();
            params.width = 650;
            window.setAttributes(params);
        }
        progressDialog.show();
        // 2分钟后显示
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (progressDialog.isShowing()) {
                    cancelEnabled = true;
                    btnCancel.setEnabled(true);
                }
            }
        }, DELAY_TIME);
    }

    public void dismissProgressDialog() {
        if (progressDialog != null && progressDialog.isShowing()) progressDialog.dismiss();
    }

    public void updateProgress(int progress) {
//        while (progress <= 97) {
            progressBar.setProgress(progress);
            tvProgress.setText(progress + "%");
//        }
    }

    public void setOnCancelListener(Runnable cancelAction) {
        btnCancel.setOnClickListener(v->{
            if (cancelEnabled) {
                cancelAction.run();
                dismissProgressDialog();
            }
        });
    }
}

这篇文章提供全部代码和操作思路,拿来就可以使用。

如果觉得还不错,给个一键三连呗~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2055895.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习第十四章-概率图模型

目录 14.1 隐马尔可夫模型 14.2马尔科夫随机场 14.3条件随机场 14.4学习与推断 14.4.1变量消去 14.4.2信念传播 14.5近似推断 14.5.1 MCMC采样 14.5.2 变分推断 14.6 话题模型 14.1 隐马尔可夫模型 概率围棋型是一类用图来表达变量相关关系的概率模型.它以图为表示工具…

Transformer(课程笔记)

一&#xff1a;Motivation RNN需要顺序的执行&#xff0c;不利于并行计算。 RNN的变体例如GRU、LSTM等需要依靠注意力机制解决信息瓶颈等问题。 抛弃RNN结构&#xff0c;提出了Transformer结构。 Transformer整体架构 二&#xff1a; 输入层&#xff08;BPE&#xff0c;PE&…

《黑神话:悟空》玩家必看!AMD显卡驱动24.8.1版全力支持!

系统之家于8月20日发出最新报道&#xff0c;AMD发布了最新的24.8.1版本驱动&#xff0c;本次更新增加了《黑神话&#xff1a;悟空》《星球大战&#xff1a;亡命之徒》等游戏的支持&#xff0c;且HYPR Tune支持允许HYPR-RX启用游戏内技术。下面跟随小编一起来看看AMD显卡驱动24.…

Centos7 message日志因dockerd、kubelet、warpdrive、containerd等应用迅速增长

问题&#xff1a;公司服务器在部署一套业务后&#xff0c;message日志记录大量的dockerd、kubelet、warpdrive、containerd应用日志&#xff0c;每天增加2G大小的日志 解决方案&#xff1a; 前期吐槽下&#xff1a;发现某个帖子&#xff0c;需要会员或者花钱才能看&#xff0c…

探索网络安全的深度与广度:挑战、策略与未来展望

一、引言 在当今数字化的时代&#xff0c;网络已经成为社会运转的核心基础设施之一。从个人的日常通信、娱乐到企业的业务运营、国家的关键服务&#xff0c;几乎所有领域都依赖于网络。然而&#xff0c;随着网络的普及和应用的深化&#xff0c;网络安全问题也日益凸显&#xf…

松下弧焊机器人维修 控制柜故障 连接线修复

一、Panasonic焊接机器人控制柜与机器人的接线 机器人的控制箱&#xff0c;一定要配对使用。松下焊接机器人控制柜已经记忆了机器人的绝对原点(机器人位置控制原点)。 二、编码器电缆 (圆形连接器) 1. 接口的插头插座要注意&#xff0c;插头要插到插座中。 2. 用一手握住电缆&a…

网络原理TCP/UDP详解

目录 传输属的几种格式 1.xml&#xff1a;通过成对的标签表示键值对信息。 2.json&#xff1a;当前更主流一点的&#xff0c;网络通信的数据格式 3.yml&#xff08;yaml&#xff09;强制要求数据的组织格式 4.google protobuffer 传输层 1.端口号&#xff1a; UDP协议 …

Vue3 组件管理 12 种神仙写法,灵活使用才能提高效率

SFC 单文件组件 顾名思义&#xff0c;就是一个.vue文件只写一个组件 模板写法 如果这个组件想要在别的组件里使用&#xff0c;就需要在另一个.vue中引入和使用、复用 h函数写法 使用 defineComponent h 去进行组件编写 JSX/TSX写法 使用 defineComponent JSX/TSX 去进行…

【html+css 绚丽Loading】 - 000008 三才虚空灵瞳

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽Loading&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495…

应用方案 | 降压型DC-DC电源管理电路 D2576介绍

概述 D2576是一款高效降压型DC-DC转换器&#xff0c;固定52KHz开关频率&#xff0c;可以提供最高3A输出电流能力&#xff0c;具有低纹波&#xff0c;出色的线性调整率与负载调整率特点。 D2576内置固定频率振荡器与频率补偿电路&#xff0c;简化了电路设计。PWM控制环路可以调节…

Rivian暂停亚马逊送货车生产,特斯拉Roadster再引关注

Rivian遭遇供应链挑战&#xff0c;暂停亚马逊送货车生产 电动汽车制造商Rivian近期宣布&#xff0c;由于零部件短缺&#xff0c;已暂停为零售巨头亚马逊生产商业送货车。这一决定标志着Rivian在应对供应链挑战方面遭遇了最新挫折。作为Rivian的最大投资者&#xff0c;亚马逊持有…

画板444

p31 画H1和H2的封装 立创里面这次有尺寸了没单位好像 给的1.02 他设的1.1焊盘可以大点 排针穿过去的&#xff08;别的焊盘也这样&#xff1f;&#xff09; 引脚编号 直接改成2.54 他焊盘直间的 距离了 刚才改成通用的直径了&#x1f605;&#x1f605;&#x1f605; 这能测尺寸…

金九银十,软件测试面试八股文【含答案+文档】

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 测试技术面试题 1、什么是兼容性测试&#xff1f;兼容性测试侧重哪些方面&#xff1f; 参考答案&#xff1a; 兼容测试主要是检查软件在不同的硬件平台、软件…

google seo基础宝典,新手必学

Google SEO 是什么&#xff1f; Google SEO是指针对谷歌搜索引擎优化网站排名的一种营销方式&#xff0c;旨在提升外贸网站在谷歌的品牌和产品曝光度&#xff0c;从而吸引外贸订单。具体做法是根据谷歌的搜索引擎排名规则&#xff0c;对网站的内容、结构、链接等方面进行优化&a…

C++竞赛初阶L1-13-第五单元-循环嵌套(29~30课)536: T456455 画矩形

题目内容 根据输入的四个参数&#xff1a;a,b,c,f 参数&#xff0c;画出对应的矩形。 前两个参数 a,b 为整数&#xff0c;依次代表矩形的高和宽&#xff1b; 第三个参数 c 是一个字符&#xff0c;表示用来填充的矩形符号&#xff1b; 第四个参数 f 为整数&#xff0c;0 代表…

测试资料2222

一 解决穷举场景&#xff1a;使用等价类划分法 适用场景 正向用例&#xff1a;一条尽可能覆盖多条 逆向用例&#xff1a;每一条数据&#xff0c;都是一条单独用例 完整的用例应该是等价类和边界值一块写 二 能对限定边界规则设计测试点 2.1选取正好等于、刚好大于、刚好小于…

搜维尔科技:【产品推荐】Manus Quantum Mocap Metagloves VR手套数据手套机械手训练专用手套

全新量子追踪技术 Quantum Mocap Metagloves通过使用毫米级精确的指尖跟踪传感器来提供高保真手指跟踪。传感器没有漂移&#xff0c;可提供高度准确且可靠的手指捕获数据。 手指追踪的新黄金标准 Quantum Mocap Metagloves使用精确的量子跟踪技术捕捉手部每一个细节动作。让您…

Unity与UE,哪种游戏引擎适合你?

PlayStation vs Xbox&#xff0c;Mario vs Sonic&#xff0c;Unreal vs Unity&#xff1f;无论是游戏主机、角色还是游戏引擎&#xff0c;人们总是热衷于捍卫他们在游戏行业中的偏爱。 专注于游戏引擎&#xff0c;Unity和Unreal Engine&#xff08;简称UE4&#xff09;是目前市…

软件测试 - 自动化测试(概念)(Java)(自动化测试分类、web自动化测试、驱动、selenium自动化测试工具的安装)

一、自动化的概念 ⾃动洒⽔机&#xff0c;主要通上⽔就可以⾃动化洒⽔并且可以⾃动的旋转。 ⾃动洗⼿液&#xff0c;免去了⼿动挤压可以⾃动感应出洗⼿液 超市⾃动闸⻔&#xff0c;不需要⼿动的开⻔关⻔ ⽣活中的⾃动化案例有效的减少了⼈⼒的消耗&#xff0c;同时也提⾼了⽣…

淘宝API常见问题解答

本文总结了4个淘宝API常见问题并给出解答&#xff0c;如果有其他关于淘宝API的问题&#xff0c;可以向点三客服提问。 问题1&#xff1a;如何获取淘宝订单&#xff0c;需用哪几个淘宝API&#xff1f; 回答&#xff1a;一般是3个淘宝API接口配合使用&#xff1a;先用taobao.trad…