【Android 远程数据库操作】

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

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

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 driverClass.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 driverClass.forName("com.mysql.jdbc.Driver");//mysql高版本这里:com.mysql.cj.jdbc.Driver// Step 2: Open a connectionConnection connection = DriverManager.getConnection(DB_URL, USER, PASS);// Step 3: Execute a queryint 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 nameString 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 * 1000private 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() {@Overridepublic 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.mzph.cn/bicheng/52324.shtml

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

相关文章

python绘制爱心代码

效果展示 完整代码 Python中绘制爱心的代码可以通过多种方式实现&#xff0c;高级的爱心代码通常指的是使用较复杂的算法或者图形库来生成更加精致的爱心图形。下面是一个使用Python的Turtle模块来绘制爱心的示例代码&#xff1a; import turtledef draw_love():turtle.speed…

[Other]-安装ruby、ascli、ascp

最近新接到这样一个需求&#xff0c;将生物原始数据上传到某中心&#xff0c;其中用到ascp命令&#xff0c;阴差阳错的装了ruby、ascli&#xff0c;这里就都一并介绍下安装方式&#xff0c;由于服务器老旧默认安装时ruby2.0&#xff0c;又 升级到2.7等引发的一系列问题&#xf…

XSS-DOM

文章目录 源码SVG标签Dom-Clobbringtostring 源码 <script>const data decodeURIComponent(location.hash.substr(1));;const root document.createElement(div);root.innerHTML data;// 这里模拟了XSS过滤的过程&#xff0c;方法是移除所有属性&#xff0c;sanitize…

AI工具革新:国内外设计艺术的融合

在人工智能的浪潮中&#xff0c;全球的创新者和开发者们推出了一系列令人惊叹的工具&#xff0c;它们正以前所未有的速度改变着我们的工作、学习和生活方式。从图像生成到语言处理&#xff0c;从数据分析到自动化设计&#xff0c;AI 作图工具展示了其强大的能力&#xff0c;帮助…

DRF——Filter条件搜索模块

文章目录 条件搜索自定义Filter第三方Filter内置Filter 条件搜索 如果某个API需要传递一些条件进行搜索&#xff0c;其实就在是URL后面通过GET传参即可&#xff0c;例如&#xff1a; /api/users?age19&category12在drf中也有相应组件可以支持条件搜索。 自定义Filter …

面试题详解

前言&#xff1a;这一期我们专门来巩固所学知识&#xff0c;同时见识一些面试题。对知识做出一个总结。 1 不创建临时变量交换两个整数 . 第一种方法 #include<stdio.h> int main() {int a 0;int b 0;scanf("%d %d", &a, &b);printf("交换前…

神经网络算法 - 一文搞懂BERT(基于Transformer的双向编码器)

本文将从BERT的本质、BERT的原理、BERT的应用三个方面&#xff0c;带您一文搞懂Bidirectional Encoder Representations from Transformers | BERT。 Google BERT BERT架构&#xff1a; 一种基于多层Transformer编码器的预训练语言模型&#xff0c;通过结合Tokenization、多种E…

Java基于数据库、乐观锁、悲观锁、Redis、Zookeeper分布式锁的简单案例实现(保姆级教程)

1. 分布式锁的定义 分布式锁是一种在分布式系统中用来协调多个进程或线程对共享资源进行访问的机制。它确保在分布式环境下&#xff0c;多个节点&#xff08;如不同的服务器或进程&#xff09;不会同时访问同一个共享资源&#xff0c;从而避免数据不一致、资源竞争等问题。 2…

等保测评服务的业务连续性规划:确保信息安全服务的韧性

在当前的数字化转型浪潮中&#xff0c;信息安全已成为企业运营的关键一环。等保测评服务作为信息安全合规的重要组成部分&#xff0c;其业务连续性规划对于保障服务的稳定性和客户信息资产的安全至关重要。本文将探讨等保测评服务的业务连续性规划策略&#xff0c;旨在构建一个…

树状数组算法

文章目录 树状数组是什么树状数组与线段树的区别与联系树状数组讲解点修&#xff0c;区查&#xff0c;讲解及模板点查&#xff0c;区修讲解及模板 树状数组是什么 树状数组是一种数据结构&#xff0c;提供O(logn)时间内的单点修改和区间求和操作&#xff0c;比线段树有更优的常…

MD编辑器学习笔记

MD编辑器学习笔记 目录标题文本样式列表图片链接代码片数学公式表格部分总结 目录 目录是使用“[TOC](目录&#xff09;”&#xff0c;记住别忘了加上&#xff08;&#xff09;标题 使用#来确定标题&#xff0c;几个#就是几级标题。记住#后面要加上空格文本样式 tips: 在写正…

物流抓取机器人整体设计方案

一、功能简介 1、运行环境&#xff1a;巡线行驶&#xff08;7路数字循迹&#xff0c;麦克纳姆轮车底盘&#xff09; 2、目标识别&#xff1a;颜色识别&#xff08;Maix-II Dock 视觉模块&#xff09; 3、目标定位&#xff1a;视觉测距&#xff08;Maix-II Dock 视觉模块&#x…

VS实⽤调试技巧(附调试例题)

&#x1f381;&#x1f381;创作不易&#xff0c;关注作者不迷路&#x1f380;&#x1f380; VS实⽤调试技巧&#xff08;附调试例题&#xff09; 前言一、什么是bug&#xff1f;二、什么是调试&#xff08;debug&#xff09;&#xff1f;三、Debug和Release四、VS调试快捷键五…

上书房信息咨询:商业项目调研方法有哪些

商业项目调研是为了了解市场需求、竞争情况和目标受众&#xff0c;从而制定合适的商业策略和项目规划。下面是一些常用的商业项目调研方法&#xff1a; 1、市场调查和问卷调查&#xff1a;通过设计和分发问卷&#xff0c;收集潜在顾客和目标市场的意见、偏好和需求。这可以帮助…

linux dig域名DNS 查询与iptables域名ip访问流量限制;PTR 反向解析从 IP 地址到域名的映射

一、域名 dns查询 在 Linux 系统中&#xff0c;你可以使用多种工具和技术来进行 DNS 查询和 IP 限制。以下是一些常用的方法和工具&#xff1a; DNS 查询 dig 命令&#xff1a; dig 是一个强大的命令行工具&#xff0c;用于查询 DNS 信息。 dig example.com你可以指定查询类型…

dockerfile搭建部署LNMP

目录 实验 架构&#xff1a; 实验步骤&#xff1a; nginx部分 mysql部分 php部分 实验 实验&#xff1a;用dockerfile搭建LNMP论坛 架构&#xff1a; 一台docker虚拟机 docker部署nginx 1.22 指定ip地址172.111.0.10 docker部署mysql 8.0.30 指定ip地址…

标准库标头 <execution> (C++17)学习

此头文件是算法库的一部分。本篇介绍策略类型的一些应用示例&#xff1a; 类 is_execution_policy (C17) 测试一个类是否表示某种执行策略 (类模板) 在命名空间 std::execution 定义 sequenced_policyparallel_policyparallel_unsequenced_policyunsequenced_policy (C17)(C1…

外排序之文件归并排序实现

外排序介绍 外排序是指能够处理极大量数据的排序算法。通常来说&#xff0c;外排序处理的数据不能一次装入内存&#xff0c;只能放在读写较慢的外存储器(通常是硬盘)上。外排序通常采用的是⼀种“排序-归并”的策略。在排序阶段&#xff0c;先读入能放在内存中的数据量&#x…

ACCESS 工具注入实战 凡诺靶场

简介 Access数据库注入攻击是一种常见的网络安全&#xff0c;通过注入SQL代码来获取未授权的数据访问权限。这种攻击利用了应用程序与数据库之间的交互漏洞&#xff0c;攻击者通过输入特定的SQL代码片段来操纵数据库查询&#xff0c;从而绕过应用程序的安全机制&#xff0c;获取…

基于x86 平台opencv的图像采集和seetaface6的人脸特征点功能

目录 一、概述二、环境要求2.1 硬件环境2.2 软件环境三、开发流程3.1 编写测试3.2 配置资源文件3.2 验证功能一、概述 本文档是针对x86 平台opencv的图像采集和seetaface6的人脸特征点功能,opencv通过摄像头采集视频图像,将采集的视频图像送给seetaface6的人脸特征点模块从而…