首先关于怎么连接mysql在我的上一篇博客已经写出,请先移步:https://blog.csdn.net/qq_40719095/article/details/105954654
以下开始怎么进行增删改查并显示到listview
一共两个类,两个布局文件,分别为:
MainActivity.java
DBUtils.java
activity_main.xml
item_xml
新建一个空项目,所有选项均为默认即可
然后在包下新建一个DBUtils类,这是数据库的工具类,里面封装增删改查和连接数据库的函数
以下为DBUtils的代码,我会在其中稍微解释以下
因为是小白所以暂时不考虑内存溢出等高级的东西,只是想能跑起来实现功能
DBUtils.java:
package com.example.mysql_second;
import android.util.Log;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class DBUtiles {
// 定义日志过滤标签
private static final String TAG="DBUtils";
// 定义全局变量conn
private static Connection conn=null;
//数据库连接函数
// 这个函数返回数据库的连接对象conn,这里写函数返回类型是Connection,因为conn是Connection类型的
// 其中的String name这个参数是在调用这个连接函数连接数据库的时候要传入数据库名dbname
public static Connection getConnection(String dbname) {
// 定义一些启动JDBC需要的参数,分别是ip地址,端口号,用户名和密码,以及创建与数据库连接时要用到的url
String ip = "10.0.2.2";
int port = 3306;
String user = "root";
String password = "root";
String url = "jdbc:mysql://" + ip + ":" + port + "/" + dbname + "?useUnicode=true&characterEncoding=UTF-8";
// "?useUnicode=true&characterEncoding=UTF-8"这一串是为了往数据库中添加中文信息的时候不会出现??或者乱码,大概意思应该是一些utf8的字符串规定
//以上完成注册JDBC前的准备事项
// 开始注册JDBC驱动,只有注册了JDBC驱动才能连接数据库
try {
// 注册语句Class.forName("com.mysql.jdbc.Driver");
// 是固定的,可能会因为mysql或者connector的jar包版本不同而有略微变化,要用try/catch语句包含
Class.forName("com.mysql.jdbc.Driver");
Log.d(TAG, "加载JDBC驱动成功");
} catch (ClassNotFoundException e) {
Log.d(TAG, "加载JDBC驱动失败");
}
// 注册完后创建与mysql的连接对象conn,通过DriverManager类的getConnection方法创建,三个参数分别是上文定义的url,user,password,同样要用try/catch包含
try {
conn = DriverManager.getConnection(url, user, password);
Log.d(TAG, "数据库连接成功");
} catch (SQLException e) {
Log.d(TAG, "数据库连接失败");
}
// 以上完成对conn的创建
// 这里一定要把创建的conn返回出去,因为在下面定义增删改查函数时需要调用这个连接函数,而且连接函数的返回类型是Connection,即conn的类型,只有return出去了,调用这个函数才能返回我们需要的conn
return conn;
}
//下面开始定义查询函数,查询函数是增删改查里最复杂的,有了这个函数在进行增删改的操作时就能直接调用查询函数进行实时更新
//数据库查询函数
//返回类型是List<HashMap<String,Object>>,因为等下在主函数中我是用simpleAdapter的方法往listview中添加数据的,所以这里直接返回List嵌套map的数据类型,免得还要一步步转数据类型
//这个函数也有一个参数,同样是数据库名,这些参数都是可以自定义的
public static List<HashMap<String,Object>> getinfo(String dbname) throws SQLException {
// 先定义一个List<HashMap<String,Object>>类型的数据并实例化
List<HashMap<String,Object>> list=new ArrayList<HashMap<String, Object>>();
// 调用连接函数,传入数据库名的形参,获得conn对象,因为getConnection的返回类型就是Connection及conn
Connection conn=getConnection(dbname);
// 由conn对象创建执行sql语句的对象(Statement类型),调用方法createStatement()
Statement sta=conn.createStatement();
// 定义sql语句
String sql="select * from emp ";
// 调用Statement对象执行sql语句,返回结果result是ResultSet类型,就是结果集,具体百度
ResultSet result=sta.executeQuery(sql);
// 判断一下是否为空
if (result==null){
return null;
}
// 条件是当结果集是否有下一行,这是一个相当于指针的东西,第一次调用时会把第一行设置为当前行,第二次回吧第二行设置为当前行,以此类推,直到没有下一行,循环结束
while (result.next()) {
// 每次循环都会新实例化一个HashMap对象,用于将遍历到的数据填进去
HashMap<String,Object> map=new HashMap<>();
// 往map中填数据,map的数据类型相当于键值对
// 键是name,值是result.getString("empname"),意思是结果集指针所在行的字段名中的数据
map.put("name",result.getString("empname"));
// 每次循环完就添加到list中,最终list的样子是:[{name=xx},{name=aaa},.......]
list.add(map);
}
// 最后记得把list返回出去,不然拿不到这个list
return list;
}
//以下是增删改函数,这些函数都不需要返回什么数据,所以都是void类型的函数,因为只要每次增删改完了以后,用查询函数重查一遍返回一个新的list就可以了,显示出来的数据就是已经增删改过后的数据
//数据库添加函数
// 传入参数数据库名,可自由diy
public static void insert(String dbname) throws SQLException {
// 同样先调用连接数据库函数,拿到连接对象
Connection conn=getConnection(dbname);
// 同样创建sql语句执行对象
Statement sta=conn.createStatement();
// 定义sql语句
String sql="insert into emp values(66666666,'csdn博客',98765,1)";
// Statement对象执行sql语句
sta.execute(sql);
}
// 以下不再赘述,一样
//数据库删除函数
public static void delete(String dbname,String empname) throws SQLException {
Connection conn=getConnection(dbname);
Statement sta=conn.createStatement();
String sql="delete from emp where empname="+"'"+empname+"'";
sta.execute(sql);
}
//数据库更新函数
public static void update(String dbname,String empname) throws SQLException {
Connection conn=getConnection(dbname);
Statement sta=conn.createStatement();
String sql="update emp set empname='阿巴阿巴阿巴阿巴阿巴阿巴' where empname="+"'"+empname+"'";
sta.executeUpdate(sql);
}
}
解释都写在代码段里,可能比较啰嗦,不过个人感觉写的很细了,罗索九罗嗦吧。
这里因为只是演示,所以sql语句我都写死了,实际可以自己diy,通过获取参数再传入对应的函数来执行
接下来先上主函数的布局文件activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<Button
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:width="1dp"
android:text="添加">
</Button>
<Button
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:width="1dp"
android:text="删除">
</Button>
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:width="1dp"
android:text="更新">
</Button>
<Button
android:id="@+id/query"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:width="1dp"
android:text="查找">
</Button>
</LinearLayout>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</ListView>
</LinearLayout>
界面是这样的:
比较简陋
这里先讲一下思路,设置四个按钮,分别是增加,删除,更新,查找,然后下面是listview显示数据,为每一个按钮添加点击事件,点击事件中分为三个部分,第一,要写在最前面的,Handler对象,这部分负责处理由子线程传出的数据,因为我们要让数据显示在主线程中的UI控件中即listview控件中,又因为在子线程中不能对UI进行更新处理,所以要把需要的数据从子线程中拿出来放到Handler中处理并进行UI更新;第二,连接数据库并执行相应增删改查操作;第三,将第二部分的操作结果通过message送到handler中。其中第二第三部分写在同一个子线程中,因为对数据库的操作都要写在子线程中而不能写在主线程中,听说是因为Android Studio对这种耗时操作的改进,就规定不能写在主线程中。
MainActivity.java:
package com.example.mysql_second;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.annotation.SuppressLint;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityRecord;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.xml.transform.Templates;
public class MainActivity extends AppCompatActivity {
// 定义一个日志信息过滤标签,测试用
private static final String TAG="DBUtils";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取按钮组件
Button add=findViewById(R.id.add);
Button delete=findViewById(R.id.delete);
Button update=findViewById(R.id.update);
Button query=findViewById(R.id.query);
//*************查找按钮功能****************************************************************************
query.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 在点击事件里写内容
//-----------------------------------------
// Handler部分
// 由子线程传出的数据在这里处理
@SuppressLint("HandlerLeak")
// 先new一个Handler对象
final Handler handler =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
// 获取listview组件,因为我们要在这个部分更新UI组件
final ListView listView=findViewById(R.id.listview);
// if的判断条件是区分msg是哪一条,即msg的ID
if(msg.what==1){
// 获取发送过来的msg.obj对象,因为我传的是List<HashMap<String, Object>>类型的obj,所以这边同样用List<HashMap<String, Object>> list去接收,要强转
List<HashMap<String,Object>> list= (List<HashMap<String, Object>>) msg.obj;
// 定义SimpleAdapter,参数分别为当前上下文,刚拿到的数据集合list,子项布局文件,数据集合中的字段信息,要添加到的子布局文件中的控件ID
SimpleAdapter simpleAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.item,new String[]{"name"},new int[]{R.id.itemtext});
// 为listview设置适配器
listView.setAdapter(simpleAdapter);
}
}
};
// Handler部分
//----------------------------------------------------------------------
//--------------------------------------------------------------
// 连接数据库并进行相应操作的线程
// 第二、第三部分
// new 一个线程,接下来是数据库操作部分,要在子线程中执行
Thread thread=new Thread(new Runnable() {
// 定义一个子线程中的全局变量List<HashMap<String,Object>> list1,用于接收从DBUtils中返回的list
List<HashMap<String,Object>> list1=new ArrayList<HashMap<String, Object>>();
@Override
public void run() {
// 与数据库建立连接
DBUtiles.getConnection("company");
try {
// 以下这些要用try/catch包含
// 调用数据库工具类的getinfo函数,用list1接收返回的list数据
list1=DBUtiles.getinfo("company");
// 打印日志,测试用
Log.d(TAG, list1.toString());
} catch (SQLException e) {
e.printStackTrace();
}
// 将从数据库拿到的list1对象传给message再由handler传出,再在handler中处理,可进行更新UI
// 新建一个message对象,尽量不要直接new,而是用这种方法,因为有内存的问题存在
Message message=Message.obtain();
// 设置message的辨认码,这里设为1
message.what=1;
// 把刚才接收到的list1赋给message.obj对象
message.obj=list1;
// 通过handler将携带数据的message传出去,传到handler中
handler.sendMessage(message);
}
});
// 上面线程定义完了,现在启动线程
thread.start();
// 第二、第三部分
//------------------------------------------------
}
});
//***********************************************************************************
//以下增删改功能和以上相同,区别只在于要在调用连接函数和查找函数之间加一个增或删或改函数,其余结构一模一样
//*************添加按钮功能****************************************************************************
add.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 由子线程传出的数据在这里处理-----------------------------------------
@SuppressLint("HandlerLeak")
final Handler handler =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
final ListView listView=findViewById(R.id.listview);
if(msg.what==1){
List<HashMap<String,Object>> list= (List<HashMap<String, Object>>) msg.obj;
SimpleAdapter simpleAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.item,new String[]{"name"},new int[]{R.id.itemtext});
listView.setAdapter(simpleAdapter);
}
}
};
//-------------------------------------------
//-------------------------------------------连接数据库线程并添加
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
DBUtiles.getConnection("company");
// 连接数据库
try {
// 添加数据
DBUtiles.insert("company");
List<HashMap<String,Object>> list1=new ArrayList<HashMap<String, Object>>();
list1=DBUtiles.getinfo("company");
Log.d(TAG, list1.toString());
// 以下这些也可以new一个新的线程执行,我这里是做成添加了立刻刷新列表的效果所以添加完数据立刻获取list并通过message发送出去再添加到适配器中
// 将从数据库拿到的list1对象传给message再由handler传出,再在Handler中处理,可进行更新UI
Message message=Message.obtain();
message.what=1;
message.obj=list1;
handler.sendMessage(message);
} catch (SQLException e) {
e.printStackTrace();
}
}
});
thread.start();
//-------------------------------------------------
}
});
//***********************************************************************************
//*************删除按钮功能****************************************************************************
delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//-----------------------------------------
// 由子线程传出的数据在这里处理
@SuppressLint("HandlerLeak")
final Handler handler =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
final ListView listView=findViewById(R.id.listview);
if(msg.what==1){
List<HashMap<String,Object>> list= (List<HashMap<String, Object>>) msg.obj;
SimpleAdapter simpleAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.item,new String[]{"name"},new int[]{R.id.itemtext});
listView.setAdapter(simpleAdapter);
}
}
};
//-------------------------------------------
//-------------------------------------------连接数据库线程并删除
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
DBUtiles.getConnection("company");
try {
DBUtiles.delete("company","我等会会被删掉");
List<HashMap<String,Object>> list1=new ArrayList<HashMap<String, Object>>();
list1=DBUtiles.getinfo("company");
Log.d(TAG, list1.toString());
// 以下这些也可以new一个新的线程执行,我这里是做成添加了立刻刷新列表的效果所以添加完数据立刻获取list并通过message发送出去再添加到适配器中
// 将从数据库拿到的list1对象传给message再由handler传出,再在Handler中处理,可进行更新UI
Message message=Message.obtain();
message.what=1;
message.obj=list1;
handler.sendMessage(message);
} catch (SQLException e) {
e.printStackTrace();
}
}
});
thread.start();
//-------------------------------------------------
}
});
//***********************************************************************************
//*************更新按钮功能****************************************************************************
update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//-----------------------------------------
// 由子线程传出的数据在这里处理
@SuppressLint("HandlerLeak")
final Handler handler =new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
final ListView listView=findViewById(R.id.listview);
if(msg.what==1){
List<HashMap<String,Object>> list= (List<HashMap<String, Object>>) msg.obj;
SimpleAdapter simpleAdapter=new SimpleAdapter(MainActivity.this,list,R.layout.item,new String[]{"name"},new int[]{R.id.itemtext});
listView.setAdapter(simpleAdapter);
}
}
};
//-------------------------------------------
//-------------------------------------------连接数据库线程并更新
Thread thread=new Thread(new Runnable() {
@Override
public void run() {
DBUtiles.getConnection("company");
try {
DBUtiles.update("company","小d");
List<HashMap<String,Object>> list1=new ArrayList<HashMap<String, Object>>();
list1=DBUtiles.getinfo("company");
Log.d(TAG, list1.toString());
// 以下这些也可以new一个新的线程执行,我这里是做成添加了立刻刷新列表的效果所以添加完数据立刻获取list并通过message发送出去再添加到适配器中
// 将从数据库拿到的list1对象传给message再由handler传出,再在Handler中处理,可进行更新UI
Message message=Message.obtain();
message.what=1;
message.obj=list1;
handler.sendMessage(message);
} catch (SQLException e) {
e.printStackTrace();
}
}
});
thread.start();
//-------------------------------------------------
}
});
//***********************************************************************************
}
}
item.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/itemtext"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TextView>
</LinearLayout>
以下为演示
我的数据库的字段分别是empid,empname,sal,dept_id
然后显示出来的只有empname字段
实现的功能是:
查找所有数据:点击按钮显示所有数据的empname字段
添加一条数据:(66666666,‘csdn博客’,98765,1)
删除一条数据:删除empname="我等会会被删掉"的数据
更新一条数据:把empname="小d"的数据改为empname=“阿巴阿巴阿巴阿巴阿巴阿巴”
原始数据:
点击了查找
点击了添加
点击了删除
点击了更新
这个demo做的很死,不过看懂了就可以拿去做diy,那个DBUtils工具类可以直接拿去改,就是这个代码写的比较乱因为找不到把mysql显示到listview的教程自己琢磨出来的,还有conn,sta等需要关闭我也没做,内存泄漏的问题吧好像,mysql连android本来应该要用服务器端的,但是我不会。所以先简单的用JDBC直连了。
仅作为学习笔记,有同样搞mysql直连android的朋友可以交流交流