Android——数据库存储(简单使用增、删、改、查)(含源码下载)
Android 系统集成了一个轻量级的关系数据库—— SQLite。其优点是占用资源少,运行效率高、安全可靠、可移植性强,并且提供零配
置运行模式,适用于在资源有限的设备(如手机和平板电脑等)上进行数据存取。
在开发手机应用时,一般会通过代码来动态创建数据库,即在程序运行时,首先尝试打开数据库,如果数据库不存在,则自动创建该数据库,然后再打开数据库。下面介绍如何通过代码来创建以及操作数据库。
一、数据库的创建
在 Android 的 SQLite 数据库中,提供了两种创建数据库的方法,分别是:
方法一:SQLiteDatabase 提供了openOrCreateDatabase() 方法来打开或创建一个数据库,语法如下:
static SQLiteDatabase openOrCreateDatabase(String path, SQLiteDatabase.CursorFactory factory)
例如,使用 openOrCreateDatabase() 方法创建一个名称为 user.db 的数据库的代码如下:
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase("user.db", null);
方法二: 通过 SQLiteOpenHelper 类创建数据库在 Android 中,提供了一个数据库辅助类 SQLiteOpenHelper。在该类的构造器中,调用Context 中的方法创建并打开一个指定名称的数据库。我们在应用这个类时,需要编写继承自SQLiteOpenHelper 类的子类,并且重写 onCreate() 和 onUpgrade() 方法。
本例着重介绍方法二的使用。
我们创建一个SQLiteOpenHelper的子类MySQLiteOpenHelper。代码如下:
MySQLiteOpenHelper.java
package com.example.mydemo;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import androidx.annotation.Nullable;public class MySQLiteOpenHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "noteBase.db"; private static final int VERSION = 1; //这是一条数据库常用语句,用于创建一个新表 private static final String table = "create table " + DBSchema.TABLE_NAME +"("+ "_id integer primary key autoincrement,"+ DBSchema.UUID+","+ DBSchema.CONTENT+","+ DBSchema.DATE+")"; public MySQLiteOpenHelper(@Nullable Context context) { //重写构造方法并设置工厂为null super(context, DATABASE_NAME, null, VERSION); } @Override public void onCreate(SQLiteDatabase db) { //下面的语句会执行数据库语句创建新表 db.execSQL(table); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public static class DBSchema{ public static final String TABLE_NAME = "custom"; public static final String UUID = "uuid"; public static final String CONTENT = "content"; public static final String DATE = "date"; }}
二、增删改查的使用
SQLiteDatabase 类提供了 insert(……)(增)、update(……)(改)、delete(……) (删)和 query(……)(查) 方法,这些方法封装了执行增删改查操作的 SQL 命令,所以我们可以使用这些方法来完成对应的操作,而不用去编写 SQL 语句了。
(1)添加操作
SQLiteDatabase 类提供了 insert() 方法用于向表中插入数据。insert() 方法的基本语法格式如下:
public long insert (String table, String nullColumnHack, ContentValues values)
◆ table:用于指定表名。
◆ nullColumnHack:可选的,用于指定当 values 参数为空时,将哪个字段设置为 null,如果values 不为空,则该参数值可以设置为 null。
◆ values:用于指定具体的字段值,它相当于 Map 集合,也是通过键值对的形式存储值的。
(2)更新操作
SQLiteDatabase 类提供了 update() 方法用于更新表中的数据。update() 方法的基本语法格式如下:
public int update(String table, ContentValues values, String whereClause, String[] whereArgs)
◆ table:用于指定表名。
◆ values:用于指定要更新的字段及对应的字段值,它相当于 Map 集合,也是通过键值对的形式存储值的。
◆ whereClause:用于指定条件语句,可以使用占位符(?)。
◆ whereArgs:当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
(3)删除操作
SQLiteDatabase 类提供了 delete() 方法用于从表中删除数据。delete() 方法的基本语法格式如下:
public int delete(String table, String whereClause, String[] whereArgs)
◆ table:用于指定表名。
◆ whereClause:用于指定条件语句,可以使用占位符(?)。
◆ whereArgs:当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
(4)查询操作
SQLiteDatabase 类提供了 query() 方法用于查询表中的数据。query() 方法的基本语法格式如下:
public Cursor query( String table, String[] columns, String selection, String[] selectionArgs, String groupBy,String having,String orderBy,String limit);
◆ table:用于指定表名。
◆ columns:用于指定要查询的列。若为空,则返回所有列。
◆ selection:用于指定 where 子句,即指定查询条件,可以使用占位符(?)。
◆ selectionArgs:where 子句对应的条件值,当条件表达式中包含占位符(?)时,该参数用于指定各占位参数的值。如果不包括占位符,该参数值可以设置为 null。
◆ groupBy:用于指定分组方式。
◆ having:用于指定 having 条件。
◆ orderBy:用于指定排序方式,为空表示采用默认排序方式。
◆ limit:用于限制返回的记录条数,为空表示不限制。query() 方法的返回值为 Cursor 对象。该对象中保存着查询结果,但是这个结果并不是数据集合的完整复制,而是数据集的指针。通过它提供的多种移动方式,我们可以获取数据集合中的数据。
Cursor 类提供的常用方法如下表所示:
这里演示一个实例作为参考:
下面贴出源码:
MySQLiteOpenHelper.java与上面数据库的创建方法二相同,不在赘述。
Note.java
package com.example.mydemo;import java.util.Date;import java.util.UUID;public class Note { //给每个Note实例添加加一个唯一识别码,这个是独一无二的 private String uuId; private String content; private Date date; public Note() { this.date = new Date(); uuId = UUID.randomUUID().toString(); } public void setUuId(String uuId) { this.uuId = uuId; } public String getUuId() { return uuId; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public Date getDate() { return date; } public void setDate(long date) { this.date = new Date(date); }}
NoteLab .java
package com.example.mydemo;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.util.Log;import java.util.ArrayList;import java.util.List;public class NoteLab { private static NoteLab sNoteLab; private SQLiteDatabase database ; //用于暂存数据库的数据 private List<Note> notes; //留给外界的接口,用于得到NoteLab实例 public static NoteLab createNoteLab(Context context){ if (sNoteLab == null){ sNoteLab = new NoteLab(context); } return sNoteLab; } //构造方法私有,使得只能通过createNoteLab(……)方法创建NoteLab实例 private NoteLab(Context context) { database = new MySQLiteOpenHelper(context).getWritableDatabase(); updateNotes(); } //插入数据 public void addData(Note note) { ContentValues values = getValues(note); database.insert(MySQLiteOpenHelper.DBSchema.TABLE_NAME,null,values); updateNotes(); } //查询数据 public List<Note> queryData(String whereClause,String[] whereArgs) { Cursor cursor = database.query( MySQLiteOpenHelper.DBSchema.TABLE_NAME, null, whereClause, whereArgs, null, null, null ); List<Note> notes = new ArrayList<>(); cursor.moveToFirst(); try{ while (!cursor.isAfterLast()){ notes.add(getNote(cursor)); cursor.moveToNext(); } } finally { cursor.close(); } return notes; } //在查询数据是使用,用于返回Note实例 private Note getNote(Cursor cursor) { Note note = new Note(); String uuId = cursor.getString(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.UUID)); String content = cursor.getString(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.CONTENT)); long date = cursor.getLong(cursor.getColumnIndex(MySQLiteOpenHelper.DBSchema.DATE)); note.setUuId(uuId); note.setContent(content); note.setDate(date); return note; } //更新数据 public void updateDate(int position,String content) { Note note = notes.get(position); note.setContent(content); ContentValues values = getValues(note); database.update( MySQLiteOpenHelper.DBSchema.TABLE_NAME, values, MySQLiteOpenHelper.DBSchema.UUID + "= ?", new String[]{ note.getUuId()} ); updateNotes(); } //删除数据 public void deleteData(int position) { Note note = notes.get(position); database.delete( MySQLiteOpenHelper.DBSchema.TABLE_NAME, MySQLiteOpenHelper.DBSchema.UUID + "= ?", new String[]{ note.getUuId()} );// database.delete(MySQLiteOpenHelper.DBSchema.TABLE_NAME,null,null); Log.i("删除数据", "deleteData: "+position); updateNotes(); } //返回一个ContentValues实例,方便插入和更新数据使用 private ContentValues getValues(Note note) { ContentValues values = new ContentValues(); String uuId = note.getUuId(); String content = note.getContent(); long date = note.getDate().getTime(); values.put(MySQLiteOpenHelper.DBSchema.UUID,uuId); values.put(MySQLiteOpenHelper.DBSchema.CONTENT,content); values.put(MySQLiteOpenHelper.DBSchema.DATE,date); return values; } //用于更新暂存数据库的数据实例notes private void updateNotes() { notes = queryData(null,null); }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout 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:background="#E2DFDF" tools:context=".MainActivity"> <TextView android:id="@+id/tv_date" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:layout_marginEnd="5dp" android:layout_marginRight="5dp" android:background="#ffffff" android:text="/????????????????/" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="@+id/textView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:text="日期:" android:textSize="30sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/et_content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="10dp" android:layout_marginEnd="5dp" android:layout_marginRight="5dp" android:background="#ffffff" android:hint="请输入内容 !" android:textSize="30sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv_date" tools:ignore="MissingConstraints" /> <EditText android:id="@+id/et_flag" android:layout_width="0dp" android:layout_height="wrap_content" android:background="#ffffff" android:gravity="center" android:textSize="30sp" app:layout_constraintBottom_toBottomOf="@+id/btn_confirm" app:layout_constraintEnd_toEndOf="@+id/btn_num" app:layout_constraintStart_toStartOf="@+id/btn_num" app:layout_constraintTop_toTopOf="@+id/btn_update" /> <Button android:id="@+id/btn_confirm" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="10dp" android:layout_marginEnd="10dp" android:layout_marginRight="10dp" android:text="插入数据" android:textSize="25sp" app:layout_constraintEnd_toStartOf="@+id/et_flag" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/et_content" /> <Button android:id="@+id/btn_query" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="20dp" android:layout_marginEnd="10dp" android:layout_marginRight="10dp" android:text="查询结果" android:textSize="25sp" app:layout_constraintEnd_toStartOf="@+id/btn_num" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btn_confirm" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:text="内容:" android:textSize="20sp" app:layout_constraintBottom_toBottomOf="@+id/tv_query_content" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="@+id/tv_query_content" /> <TextView android:id="@+id/tv_query_content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginLeft="5dp" android:layout_marginTop="10dp" android:layout_marginEnd="5dp" android:layout_marginRight="5dp" android:background="#ffffff" android:text="TextView" android:textSize="20sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/textView3" app:layout_constraintTop_toBottomOf="@+id/btn_query" /> <Button android:id="@+id/btn_update" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginLeft="10dp" android:layout_marginEnd="5dp" android:layout_marginRight="5dp" android:text="更新数据" android:textSize="25sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/et_flag" app:layout_constraintTop_toTopOf="@+id/btn_confirm" /> <Button android:id="@+id/btn_delete" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="10dp" android:layout_marginLeft="10dp" android:layout_marginEnd="5dp" android:layout_marginRight="5dp" android:text="删除数据" android:textSize="25sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/btn_num" app:layout_constraintTop_toTopOf="@+id/btn_query" /> <Button android:id="@+id/btn_num" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:text="数据量" app:layout_constraintBottom_toBottomOf="@+id/btn_query" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/et_flag" /></androidx.constraintlayout.widget.ConstraintLayout>
MainActivity .java
package com.example.mydemo;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import java.util.List;public class MainActivity extends AppCompatActivity { private Button mBtnConfirm; private Button mBtnQuery; private Button mBtnUpdate; private Button mBtnDelete; private Button mBtnDataNum; private EditText mEtContent; private EditText mEtFlag; private TextView mTvDate; private TextView mTvContentQuery; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //绑定布局中的控件 initView(); //为各个控件设置执行命令 initEvent(); } //得到当前数据库有多少条数据 private int getNoteNum() { int noteNum = NoteLab.createNoteLab(getApplicationContext()) .queryData(null,null) .size(); return noteNum; } private void initEvent() { mEtFlag.setText(getNoteNum() + ""); mEtContent.setText(""); //插入数据 mBtnConfirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mEtContent.getText().toString().length() != 0){ Note note = new Note(); note.setContent(mEtContent.getText().toString()); mTvDate.setText(note.getDate().toString()); mEtContent.setText(""); NoteLab.createNoteLab(getApplicationContext()).addData(note); } else { Toast.makeText(MainActivity.this,"插入数据失败 !",Toast.LENGTH_SHORT) .show(); } } }); //查询数据 mBtnQuery.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { List<Note> notes = NoteLab.createNoteLab(getApplicationContext()) .queryData(null,null); int position = Integer.parseInt(mEtFlag.getText().toString())-1; if ((position >= 0) && (position < getNoteNum())){ Note note = notes.get(position); mTvContentQuery.setText(note.getContent()+"\n\n"+note.getDate()); } else { mTvContentQuery.setText(""); Toast.makeText(MainActivity.this,"查询数据失败 !",Toast.LENGTH_SHORT) .show(); } } }); //更新数据 mBtnUpdate.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = Integer.parseInt(mEtFlag.getText().toString())-1; if ((position >= 0) && (position < getNoteNum())){ Log.i("更新数据position",position+""); Log.i("更新数据getNoteNum",getNoteNum()+""); NoteLab.createNoteLab(getApplicationContext()) .updateDate(position,mEtContent.getText().toString()); } else { Toast.makeText(MainActivity.this,"更新数据失败 !",Toast.LENGTH_SHORT) .show(); } } }); //删除数据 mBtnDelete.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int position = Integer.parseInt(mEtFlag.getText().toString())-1; if ((position >= 0) && (position < getNoteNum())){ NoteLab.createNoteLab(getApplicationContext()) .deleteData(position); } else { Toast.makeText(MainActivity.this,"删除数据失败 !",Toast.LENGTH_SHORT) .show(); } } }); //获取数据量 mBtnDataNum.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mEtFlag.setText(getNoteNum()+""); } }); } private void initView() { mBtnConfirm = findViewById(R.id.btn_confirm); mBtnQuery = findViewById(R.id.btn_query); mBtnUpdate = findViewById(R.id.btn_update); mBtnDelete = findViewById(R.id.btn_delete); mBtnDataNum = findViewById(R.id.btn_num); mEtContent = findViewById(R.id.et_content); mEtFlag = findViewById(R.id.et_flag); mTvDate = findViewById(R.id.tv_date); mTvContentQuery = findViewById(R.id.tv_query_content); }}
链接:百度网盘下载 提取码:0d1d
更多相关文章
- 一句话锁定MySQL数据占用元凶
- Android异步消息处理机制 深入理解Looper、Handler、Message的关
- 打造通用的Android下拉刷新组件(适用于ListView、GridView等各类
- 详解android的号码匹配
- Binder框架在Framework层的C++中的使用
- Android(安卓)修改字体,跳不过的 Typeface
- android多线程详解之Handler
- [置顶] Android之路——第一个上线 APP项目总结
- 新建Android工程并引用其他工程当做类库 报错解决方法