Java-Spring入门指南(三十二)Android SQLite数据库实战:手把手实现用户信息CRUD完整系统
- 前言
- 前置准备
- 一、Android中SQLite核心概念
-
- [1.1 核心组件关系](#1.1 核心组件关系)
- [1.2 关键设计原则](#1.2 关键设计原则)
- 二、项目结构总览
- 三、代码实现
-
- [3.1 实体类:User(数据模型)](#3.1 实体类:User(数据模型))
- [3.2 数据库核心:UserDBHelper(SQLiteOpenHelper子类)](#3.2 数据库核心:UserDBHelper(SQLiteOpenHelper子类))
- [3.3 界面交互:UserActivity(核心Activity)](#3.3 界面交互:UserActivity(核心Activity))
- [3.4 界面布局:activity_user.xml](#3.4 界面布局:activity_user.xml)
- [3.5 清单文件:AndroidManifest.xml](#3.5 清单文件:AndroidManifest.xml)
- 四、运行测试
-
- [4.1 测试步骤](#4.1 测试步骤)
- [4.2 预期效果](#4.2 预期效果)
前言
上一篇我们深度解析了Android的Intent组件,掌握了跨组件通信的核心方式。但在实际开发中,应用往往需要本地存储数据 ------比如保存用户账号密码、缓存配置信息等,此时就需要用到Android内置的轻量级数据库SQLite。
SQLite是Android原生支持的关系型数据库,无需额外安装,占用资源少、操作简单,非常适合存储本地结构化数据。本文将基于Android Studio + 模拟器环境,通过"实体类→数据库助手→界面交互"的完整流程,实现用户信息的新增、查询、修改、删除(CRUD) 功能,最终完成一个可直接运行的本地数据库系统。
我的个人主页,欢迎阅读其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的Java-Spring入门指南专栏
欢迎指出不足
https://blog.csdn.net/2402_83322742/category_13040333.html?spm=1001.2014.3001.5482

前置准备
开始前先确保以下工具和环境已就绪:
- 开发工具:Android Studio 2025.1.4;
- JDK:17(Android Studio默认集成,无需额外配置);
- 模拟器:Android 14(API 34)或其他兼容版本(确保能正常运行);
- 核心依赖:Android原生SDK(无需额外导入第三方库,SQLite已内置)。
一、Android中SQLite核心概念
Android操作SQLite的核心是SQLiteOpenHelper类------它是Google提供的数据库辅助工具,封装了数据库的创建、升级、连接管理等底层逻辑,开发者无需直接编写复杂的SQL连接代码。
1.1 核心组件关系
| 组件 | 作用 | 类比后端角色 |
|---|---|---|
SQLiteOpenHelper |
数据库创建、升级、连接管理 | 数据库连接池(如C3P0)+ 建表脚本 |
SQLiteDatabase |
执行具体SQL操作(增删改查) | JDBC的Statement/PreparedStatement |
实体类(如User) |
封装数据模型(对应数据库表) | 后端POJO/Entity类 |
Activity(如UserActivity) |
界面交互+调用数据库操作 | 后端Controller(接收请求+调用Service) |
1.2 关键设计原则
- 单例模式 :
SQLiteOpenHelper实例需全局唯一,避免多线程下数据库连接冲突; - 连接管理:使用时打开数据库连接(读/写),用完后及时关闭,避免资源泄漏;
- CRUD封装 :将数据库操作(增删改查)封装在
SQLiteOpenHelper子类中,Activity仅调用方法,解耦界面与数据层。
二、项目结构总览
本文项目结构
clike
com.example.ch6_1
├── MainActivity.java // 启动页(实际复用UserActivity布局)
├── UserActivity.java // 核心界面:用户交互+CRUD调用
├── User.java // 实体类:封装用户数据(id、name、pwd)
├── UserDBHelper.java // 数据库助手:SQLite核心操作封装
├── res
│ ├── layout
│ │ └── activity_user.xml // 界面布局:输入框+按钮+列表显示
│ └── values
│ └── strings.xml // 字符串资源(应用名称等)
└── AndroidManifest.xml // 清单文件:Activity注册+权限配置

三、代码实现
3.1 实体类:User(数据模型)
User类对应数据库中的user表,封装了用户的id(自增主键)、name(用户名)、pwd(密码)三个字段,提供构造方法、getter/setter和toString方法。

java
package com.example.ch6_1;
public class User {
private int id; // 自增主键(数据库自动生成)
private String name; // 用户名(唯一标识)
private String pwd; // 密码
// 无参构造(必须,SQLite查询时需反射实例化)
public User() {}
// 新增用户时使用(无需传入id,数据库自动生成)
public User(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
// 查询/修改时使用(需包含id)
public User(int id, String name, String pwd) {
this.id = id;
this.name = name;
this.pwd = pwd;
}
// Getter 和 Setter 方法(用于读写字段值)
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getPwd() { return pwd; }
public void setPwd(String pwd) { this.pwd = pwd; }
// 重写toString:方便打印用户信息(用于列表显示)
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', pwd='" + pwd + "'}";
}
}
- 关键说明:无参构造方法是必需的,SQLite查询结果映射为
User对象时,需通过反射调用无参构造。
3.2 数据库核心:UserDBHelper(SQLiteOpenHelper子类)

UserDBHelper是操作SQLite的核心类,封装了数据库创建、表创建、读写连接管理、CRUD方法,采用单例模式确保全局唯一实例。
java
package com.example.ch6_1;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
public class UserDBHelper extends SQLiteOpenHelper {
// 数据库名称(固定,后缀可自定义)
private static final String DB_NAME = "java2.db";
// 表名(用户表)
private static final String TABLE_NAME = "user";
// 单例实例(全局唯一)
private static UserDBHelper mDBHelper = null;
// 只读数据库连接(查询操作)
private SQLiteDatabase mRDB = null;
// 只写数据库连接(增删改操作)
private SQLiteDatabase mWDB = null;
// 数据库版本(升级时修改)
private static final int VERSION = 1;
// 构造方法(私有,仅单例模式内部调用)
public UserDBHelper(@Nullable Context context) {
super(context, DB_NAME, null, VERSION);
}
// 单例模式:获取UserDBHelper唯一实例(避免多实例冲突)
public static UserDBHelper getInstance(Context context) {
if (mDBHelper == null) {
mDBHelper = new UserDBHelper(context);
}
return mDBHelper;
}
// 打开只读连接(查询操作使用)
public SQLiteDatabase openReadLink() {
if (mRDB == null || !mRDB.isOpen()) {
mRDB = mDBHelper.getReadableDatabase();
}
return mRDB;
}
// 打开只写连接(增删改操作使用)
public SQLiteDatabase openWriteLink() {
if (mWDB == null || !mWDB.isOpen()) {
mWDB = mDBHelper.getWritableDatabase();
}
return mWDB;
}
// 关闭数据库连接(避免资源泄漏)
public void closeDB() {
// 关闭读连接
if (mRDB != null && mRDB.isOpen()) {
mRDB.close();
mRDB = null; // 便于GC回收
}
// 关闭写连接
if (mWDB != null && mWDB.isOpen()) {
mWDB.close();
mWDB = null; // 便于GC回收
}
}
// 数据库第一次创建时调用(仅执行一次):创建user表
@Override
public void onCreate(SQLiteDatabase db) {
// 建表SQL:id自增主键,name和pwd为字符串类型
String sql = "create table " + TABLE_NAME + "(id integer primary key autoincrement,name varchar,pwd varchar )";
db.execSQL(sql); // 执行SQL
Log.e("UserDBHelper类", "onCreate执行了:创建user表成功");
}
// 数据库版本升级时调用(VERSION修改后触发):本文暂不实现
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}
// -------------- CRUD核心方法 --------------
// 1. 新增用户
public long add(User user) {
ContentValues values = new ContentValues(); // 封装字段值(类似Map)
values.put("name", user.getName()); // 用户名
values.put("pwd", user.getPwd()); // 密码
// 插入数据:参数1=表名,参数2=空列占位符,参数3=字段值封装
long insertResult = mWDB.insert(TABLE_NAME, null, values);
return insertResult; // 返回值:成功返回行号(>0),失败返回-1
}
// 2. 查询所有用户
public List<User> querUsers() {
List<User> userList = new ArrayList<>();
// 查询所有数据:参数依次为表名、查询字段、条件、条件值、分组、筛选、排序
Cursor cursor = mRDB.query(TABLE_NAME, null, null, null, null, null, null);
// 遍历查询结果(游标移动到下一行)
while (cursor.moveToNext()) {
int id = cursor.getInt(0); // 第0列:id
String name = cursor.getString(1); // 第1列:name
String pwd = cursor.getString(2); // 第2列:pwd
userList.add(new User(id, name, pwd)); // 封装为User对象添加到列表
}
cursor.close(); // 关闭游标(必须,避免资源泄漏)
return userList; // 返回所有用户列表
}
// 3. 根据用户名删除用户
public long deleteByName(String name) {
String whereClause = "name=?"; // 条件:name等于指定值(?为占位符)
String[] whereArgs = {name}; // 条件值(替换?)
// 删除数据:参数1=表名,参数2=条件,参数3=条件值
long deleteResult = mWDB.delete(TABLE_NAME, whereClause, whereArgs);
return deleteResult; // 成功返回删除行数(>0),失败返回0
}
// 4. 根据用户名修改密码
public long updatePwdByName(String name, String newPwd) {
ContentValues values = new ContentValues();
values.put("pwd", newPwd); // 要修改的字段(密码)
String whereClause = "name=?"; // 条件:用户名
String[] whereArgs = {name}; // 用户名值
// 更新数据:参数1=表名,参数2=修改字段,参数3=条件,参数4=条件值
long updateResult = mWDB.update(TABLE_NAME, values, whereClause, whereArgs);
return updateResult; // 成功返回更新行数(>0),失败返回0
}
// 5. 根据ID删除用户(扩展方法)
public long deleteById(int id) {
String whereClause = "id=?";
String[] whereArgs = {String.valueOf(id)};
long result = mWDB.delete(TABLE_NAME, whereClause, whereArgs);
return result;
}
// 6. 根据ID修改用户信息(扩展方法)
public long updateById(int id, String newName, String newPwd) {
ContentValues values = new ContentValues();
values.put("name", newName);
values.put("pwd", newPwd);
String whereClause = "id=?";
String[] whereArgs = {String.valueOf(id)};
long result = mWDB.update(TABLE_NAME, values, whereClause, whereArgs);
return result;
}
}
- 关键说明:
ContentValues:用于封装字段名和值,避免直接拼接SQL字符串(防止SQL注入);Cursor:查询结果游标,遍历后必须关闭,否则会导致内存泄漏;- 读写分离:查询用
getReadableDatabase(),增删改用getWritableDatabase(),提高效率。
3.3 界面交互:UserActivity(核心Activity)
UserActivity负责界面展示和用户交互,通过绑定布局控件,实现"新增、查询、修改、删除"按钮的点击事件,调用UserDBHelper的CRUD方法完成数据操作,并刷新界面显示。

java
package com.example.ch6_1;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.List;
public class UserActivity extends AppCompatActivity implements View.OnClickListener {
private EditText name; // 用户名输入框
private EditText pwd; // 密码输入框
private UserDBHelper userDBHelper; // 数据库助手实例
private TextView textView; // 用户列表显示控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this); // 启用全屏(沉浸式)布局
setContentView(R.layout.activity_user); // 绑定布局
// 适配系统状态栏(避免控件被遮挡)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
// 初始化控件(绑定布局中的ID)
name = findViewById(R.id.name);
pwd = findViewById(R.id.pwd);
textView = findViewById(R.id.textView1);
// 为四个按钮设置点击事件(当前Activity实现OnClickListener接口)
findViewById(R.id.save).setOnClickListener(this);
findViewById(R.id.update).setOnClickListener(this);
findViewById(R.id.del).setOnClickListener(this);
findViewById(R.id.query).setOnClickListener(this);
}
// 按钮点击事件回调(统一处理所有按钮点击)
@Override
public void onClick(View view) {
String username = name.getText().toString().trim(); // 获取用户名(去空格)
String password = pwd.getText().toString().trim(); // 获取密码(去空格)
// 新增用户
if (view.getId() == R.id.save) {
if (username.isEmpty() || password.isEmpty()) { // 校验输入不为空
Toast.makeText(this, "用户名和密码不能为空", Toast.LENGTH_SHORT).show();
return;
}
// 调用新增方法:传入User对象
long addResult = userDBHelper.add(new User(username, password));
if (addResult > 0) {
Toast.makeText(this, "新增成功", Toast.LENGTH_LONG).show();
clearInput(); // 清空输入框
refreshUserList(); // 刷新用户列表显示
} else {
Toast.makeText(this, "新增失败", Toast.LENGTH_LONG).show();
}
}
// 查询所有用户
else if (view.getId() == R.id.query) {
refreshUserList(); // 直接刷新列表
}
// 根据用户名删除用户
else if (view.getId() == R.id.del) {
if (username.isEmpty()) { // 校验用户名不为空
Toast.makeText(this, "请输入要删除的用户名", Toast.LENGTH_SHORT).show();
return;
}
long deleteResult = userDBHelper.deleteByName(username);
if (deleteResult > 0) {
Toast.makeText(this, "删除成功", Toast.LENGTH_LONG).show();
clearInput();
refreshUserList();
} else {
Toast.makeText(this, "删除失败,用户不存在", Toast.LENGTH_LONG).show();
}
}
// 根据用户名修改密码
else if (view.getId() == R.id.update) {
if (username.isEmpty() || password.isEmpty()) { // 校验输入不为空
Toast.makeText(this, "用户名和新密码都不能为空", Toast.LENGTH_SHORT).show();
return;
}
long updateResult = userDBHelper.updatePwdByName(username, password);
if (updateResult > 0) {
Toast.makeText(this, "修改成功", Toast.LENGTH_LONG).show();
clearInput();
refreshUserList();
} else {
Toast.makeText(this, "修改失败,用户不存在", Toast.LENGTH_LONG).show();
}
}
}
// 辅助方法:刷新用户列表显示(查询所有用户并展示在TextView)
private void refreshUserList() {
List<User> userList = userDBHelper.querUsers(); // 调用查询方法
if (userList.isEmpty()) { // 无用户数据
textView.setText("暂无用户数据");
} else { // 有用户数据:拼接字符串显示
StringBuilder sb = new StringBuilder();
sb.append("用户列表:\n\n");
for (User user : userList) {
sb.append("ID: ").append(user.getId())
.append(", 用户名: ").append(user.getName())
.append(", 密码: ").append(user.getPwd())
.append("\n");
}
textView.setText(sb.toString());
}
}
// 辅助方法:清空输入框
private void clearInput() {
name.setText("");
pwd.setText("");
}
// 生命周期:Activity启动时打开数据库连接
@Override
protected void onStart() {
super.onStart();
userDBHelper = UserDBHelper.getInstance(this); // 获取单例实例
userDBHelper.openWriteLink(); // 打开写连接(增删改)
userDBHelper.openReadLink(); // 打开读连接(查询)
refreshUserList(); // 启动时自动刷新列表
}
// 生命周期:Activity停止时关闭数据库连接(避免资源泄漏)
@Override
protected void onStop() {
super.onStop();
userDBHelper.closeDB(); // 关闭所有连接
}
}
- 关键说明:
- 生命周期管理:
onStart打开数据库连接,onStop关闭,确保资源及时释放; - 输入校验:避免空值导致的数据库操作失败;
- 界面刷新:每次数据操作后调用
refreshUserList(),实时展示最新数据。
- 生命周期管理:
3.4 界面布局:activity_user.xml


采用垂直LinearLayout布局,包含两个输入框(用户名、密码)、四个功能按钮(新增、删除、修改、查询)和一个文本框(显示用户列表),布局简洁直观。
xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:lineSpacingExtra="8dp"
android:padding="12dp"
android:textColor="#333333">
<!-- 用户名输入框 -->
<EditText
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名"/>
<!-- 密码输入框 -->
<EditText
android:id="@+id/pwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码"/>
<!-- 新增按钮 -->
<Button
android:id="@+id/save"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="新增"/>
<!-- 删除按钮 -->
<Button
android:id="@+id/del"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除"/>
<!-- 修改按钮 -->
<Button
android:id="@+id/update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="修改"/>
<!-- 查询按钮 -->
<Button
android:id="@+id/query"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查询"/>
<!-- 用户列表显示控件 -->
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textSize="16sp"/>
</LinearLayout>
- 布局属性说明:
match_parent:宽度/高度占满父容器;wrap_content:宽度/高度适应内容;padding:内边距,避免控件紧贴屏幕边缘;lineSpacingExtra:控件之间的间距。
3.5 清单文件:AndroidManifest.xml
配置应用基本信息、Activity注册(设置UserActivity为启动页),。
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication">
<activity
android:name=".UserActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
- 关键配置:
android:exported="true":允许外部启动(启动页必需);intent-filter中的MAIN和LAUNCHER:指定UserActivity为应用入口。
四、运行测试
4.1 测试步骤
- 启动Android模拟器(或连接真实设备);
- 点击Android Studio的"运行"按钮,安装应用并启动;
- 功能测试:
- 新增 :输入用户名(如
zhangsan)和密码(如123456),点击"新增",提示"新增成功",再点击"查询",列表显示新增用户; - 查询:直接点击"查询",显示所有已添加的用户;
- 修改 :输入已存在的用户名(如
zhangsan)和新密码(如654321),点击"修改",提示"修改成功",查询后显示密码已更新; - 删除 :输入已存在的用户名(如
zhangsan),点击"删除",提示"删除成功",查询后列表中该用户消失。
- 新增 :输入用户名(如
4.2 预期效果


- 新增用户后,查询列表显示完整的用户ID、用户名、密码;
- 修改/删除操作后,列表实时刷新,数据与数据库保持一致;
- 输入为空时,弹出Toast提示,避免无效操作。
我的个人主页,欢迎来阅读我的其他文章
https://blog.csdn.net/2402_83322742?spm=1011.2415.3001.5343我的Java-Spring入门指南知识文章专栏
欢迎来阅读指出不足
https://blog.csdn.net/2402_83322742/category_13040333.html?spm=1001.2014.3001.5482
|--------------------|
| 非常感谢您的阅读,喜欢的话记得三连哦 |
