您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
25_数据库的增删改查
发布时间:2021-02-13 20:22:41编辑:雪饮阅读()
增
首先在布局文件activity_mai.xml中增加增、删、改、查四个按钮并定义对应触发事件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建数据库"
android:id="@+id/send_button"
android:onClick="send"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="增加一些数据"
android:id="@+id/send_add"
android:onClick="send_add"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除一条数据"
android:id="@+id/send_del"
android:onClick="send_del"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="改一条数据"
android:id="@+id/send_update"
android:onClick="send_update"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查看全部数据"
android:id="@+id/send_find_all"
android:onClick="send_find_all"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="创建数据库"
android:id="@+id/send_button"
android:onClick="send"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="增加一些数据"
android:id="@+id/send_add"
android:onClick="send_add"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="删除一条数据"
android:id="@+id/send_del"
android:onClick="send_del"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="改一条数据"
android:id="@+id/send_update"
android:onClick="send_update"
/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="查看全部数据"
android:id="@+id/send_find_all"
android:onClick="send_find_all"
/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import java.util.List;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void send(View view) {
MyDBOpenHelper helper = new MyDBOpenHelper(this);
//获取可读数据库,仅仅是new并不会创建数据库,这里执行之后才会
helper.getReadableDatabase();
}
public void send_add(View view) {
PersonDao dao = new PersonDao(this);
for(int i=0;i<100;i++){
dao.add("lisi"+i, "123456789"+i);
}
}
public void send_del(View view) {
PersonDao dao = new PersonDao(this);
dao.delete("lisi99");
}
public void send_update(View view) {
PersonDao dao = new PersonDao(this);
dao.update("lisi98", "wangwu", "119");
}
public void send_find_all(View view) {
PersonDao dao = new PersonDao(this);
List<Person> persons = dao.getAllPersons();
}
}
然后建立PersonDao.java实现上面所依赖的PersonDao的所有数据库实际操作
package com.example.myapplication;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
public class PersonDao {
private static final String TAG = "PersonDao";
private MyDBOpenHelper dbOpenHelper;
// 在personDao被new出来的时候 就完成初始化
public PersonDao(Context context) {
dbOpenHelper = new MyDBOpenHelper(context);
}
//增删改查
/**
*往数据库添加一条记录
*/
public void add(String name, String phone) {
boolean result = find(name);
if (result)
return;
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
if (db.isOpen()) {
db.execSQL("insert into person (name,phone) values (?,?)",
new Object[] { name, phone });
//关闭数据库 释放数据库连接
db.close();
}
}
/**
*查找数据库的操作
*/
public boolean find(String name) {
boolean result = false;
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
if (db.isOpen()) {
Cursor cursor = db.rawQuery("select * from person where name=?",
new String[] { name });
//相当于判断结果集是否无效(空集、sql执行错误等导致结果集没有回显)
if (cursor.moveToFirst()) {
int index = cursor.getColumnIndex("phone"); // 得到phone在表中的索引(下标)
String phone = cursor.getString(index);
Log.i(TAG, "phone =" + phone);
result = true;
}
//关闭掉cursor 释放游标
cursor.close();
result = false;
db.close();
}
return result;
}
/**
* 删除一条记录
*
* @param name
*/
public void delete(String name) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
if (db.isOpen()) {
db.execSQL("delete from person where name =?",
new Object[] { name });
db.close();
}
}
/**
* 更新一条记录
*
*/
public void update(String name, String newname, String newphone) {
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
if (db.isOpen()) {
db.execSQL("update person set name=? , phone=? where name=?",
new Object[] { newname, newphone, name });
db.close();
}
}
/**
* 查找全部
*/
public List<Person> getAllPersons() {
List<Person> persons=null;
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
if (db.isOpen()) {
persons = new ArrayList<Person>();
Cursor cursor = db.rawQuery("select * from person ", null);
while (cursor.moveToNext()) {
Person person = new Person();
int nameindex = cursor.getColumnIndex("name");
int phoneindex = cursor.getColumnIndex("phone");
String name = cursor.getString(nameindex);
String phone = cursor.getString(phoneindex);
person.setName(name);
person.setNumber(phone);
persons.add(person);
}
cursor.close();
db.close();
}
return persons;
}
}
当然,上面这个又依赖于person类,这里建立Person.java
package com.example.myapplication;
public class Person {
String name;
String number;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
然后部署项目到设备中并点击“增加一些数据”按照逻辑,则成功执行后数据表中则得到如下这些数据
查与junit3不使用断言的单元测试
这里我们测试PersonDao.java中的find方法,按照前面的测试流程建立了测试testFind,这里我默认放在C:\Users\Administrator\AndroidStudioProjects\MyApplication\app\src\androidTest\java\com\example\myapplication路径,也就是说和我的主项目不在一个路径,测试的项目单独放一个目录
然后这里用android studio建立测试用例时候默认我选择的是junit3
那么接下来在实现testFind时候由于new这个PersonDao时候需要有上下文的参数,这里不能像主项目的主控MainActivity.java中直接使用this关键字做参数
这里需要处理的如:
package com.example.myapplication;
import androidx.test.InstrumentationRegistry;
import junit.framework.TestCase;
public class PersonDaoTest extends TestCase {
public void testFind() {
PersonDao dao = new PersonDao(InstrumentationRegistry.getTargetContext()) ;
dao.find("lisi99");
}
}
可以看到该测试用例中并没有使用断言,但是这样也是可以测试通过的,这查找的lisi99,正好也在上面我们测试增加数据的时候已经建立了进去,这里测试结果也是测试通过的。
删
在测试删除功能时候,我没有使用单元测试,而是直接用设备测试,此时发现app崩溃,当再次测试时候并结合日志猫的时候发现有如下一条日志
Android studio报错database.sqlite.SQLiteException Can't downgrade database from version 2 to 1
这问题是因为前面曾经提到的sqlite数据库支持的构造时候给父类构造传参中的版本号的时候因为我之前sqlite的数据库升过级,之前填写的是2,即升级到2级,然后今天又重写了这个sqlite支持类的时候不小心把这个版本号传了1了,所以才导致如此,这里只需要重新修改回2即可,如MyDBOpenHelper.java:
package com.example.myapplication;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MyDBOpenHelper extends SQLiteOpenHelper {
public MyDBOpenHelper(Context context) {
super(context, "itheima.db", null, 2);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL ");
}
}
然后重新测试删除,就成功删除了name为lisi99的这条数据
查看全部
为了测试查看全部的效果,这里重新实现下查看全部的输出(输出到日志猫中)
在主控中MainActivity.java查看全部的实现方法更改如:
public void send_find_all(View view) {
PersonDao dao = new PersonDao(this);
List<Person> persons = dao.getAllPersons();
for(Person p:persons){
String row="name:"+p.getName()+"phone:"+p.getNumber();
Log.i("row",row);
}
}
基于命令行的sqlite数据库工具
安卓sdk中内置提供了sqlite数据库工具命令行版,但要使用该工具需要你的sdk是apis,比如像这里的google play的这种常见的版本就不行,其实也不是不行,而是sqlite数据库命令行这个版本在安卓中一般常用方法是”进入”数据库存储文件所在目录,即/data/data/com.example.myapplication/databases然后才能执行进行sqlite数据库中,但是普通sdk一般不提供su命令,su命令用来获取root权限,而像是这种非公共公开的目录普通用户是无法进入的(当然不排除其它非正常手段),废话不多说,那么接下来就安装一个和我们项目匹配的apis的sdk
安装之后最好把原来的那个itheima.db删除掉,重新构造数据库及升级到2版本,即有phone字段那个版本,然后测试如:
这里最后的limit是限制查找的数量的,由于我们新增时候一次新增的太多,防止显示的数量太多,所以这里仅仅只查出5条。
Microsoft Windows [版本 10.0.18363.1316]
(c) 2019 Microsoft Corporation。保留所有权利。
C:\Users\Administrator>cd C:\Program Files (x86)\Android\android-sdk\platform-tools
C:\Program Files (x86)\Android\android-sdk\platform-tools>adb shell
generic_x86_64:/ $ su
generic_x86_64:/ # cd /data/data/com.example.myapplication/databases
generic_x86_64:/data/data/com.example.myapplication/databases # ls
itheima.db itheima.db-shm itheima.db-wal
generic_x86_64:/data/data/com.example.myapplication/databases # sqlite3 itheima.db
SQLite version 3.22.0 2018-12-19 01:30:22
Enter ".help" for usage hints.
sqlite> select * from person limit 5;
1|lisi0|1234567890
2|lisi1|1234567891
3|lisi2|1234567892
4|lisi3|1234567893
5|lisi4|1234567894
sqlite>
关键字词:android,增删改查