按正常情况下,前端不应该直接进行远程数据库操作,这不是一个明智的方式,应该是后端提供对应接口来处理,奈何公司各方面原因需要前端这样做。
对此,我对远程数据库操作做了总结,便于自己复盘,同时,也分享给有需要的朋友们。
下载mysql官网:https://dev.mysql.com/downloads/connector/j/,按图片步骤下载所需jdbc的库
在Android studio的项目工程app-bulid.grade添加依赖:implementation files(‘libs/mysql-connector-java-5.1.48.jar’)或implementation 'mysql:mysql-connector-java:5.1.48’这两种方式
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);
String sql = "select name, age, sex from User";// sql语句 Statement statement = connection.createStatement(); ResultSet rs = statement.executeQuery(sql); while (rs.next() && !isStopped) { // todo 相应业务处理 }
// 操作完毕,数据库关闭 rs.close(); statement.close(); connection.close();
远程数据库操作工具类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(); } }); } }
这篇文章提供全部代码和操作思路,拿来就可以使用。
如果觉得还不错,给个一键三连呗~~~