【Sqlite试用】java语言

boat

  1. 视频学习来源b站:程序猿拉大锯
    在这里插入图片描述
  2. 【ctrl+N】查找SQLiteOpenHelper发现他是个抽象类,【ctrl+H】查看继承关系,其没有实现类
  3. Sql语句
    在这里插入图片描述

1. 【创建数据库】实现升级版本

1.建立一个类DatabaseHelper继承SQLiteOpenHelper

  1. 实现两个成员方法onCreate()onUpgrade() 分别是数据库第一次创建时的回调和升级数据库时的回调
  2. 复写一个四参构造方法
    a. 上下文
    b.数据库名
    c.游标工厂(用来创建游标对象,类指针,指向某一行,该行有对应的许多字段,null为默认)
    d.版本号(只能升级不能降级)
  3. 建立一个类Constances,写静态成员变量用于记录成员信息,供2中的构造方法调用,
  4. 运行虚拟机找到data/data/com.ywjh.databasedemo
    1)目前只有两个文件夹
    2)new一个help对象,传入当前上下文,就有数据库了,暂时告别sql语句
DatabaseHelper helper=new DatabaseHelper(this);//创建对象,调用构造方法创建数据库
helper.getWritableDatabase();//获取数据库

在这里插入图片描述

2. 完善增删改查,首先确定字段

  1. 理所当然的在DatabaseHelper的oncreate方法中初始化创建字段(把原数据库先删了),Constances中写个静态表名
   public void onCreate(SQLiteDatabase db) {
        Log.d(TAG,"创建数据库");
        //创建字段
        //sql create table table_name(id integer,name varchar(50),age integer,salary integer)//sqlite 都是varchar
        String sql="create table "+Constants.TABLE_NAME+"(_id integer,name varchar,age integer,salary integer)";
        db.execSQL(sql);//执行语句
    }
  1. 使用Sqlite Expert观察4个字段就有了
    在这里插入图片描述
  2. 使用一下onupdate方法添加字段(数据库名,老版本号,新版本号)
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(TAG,"升级数据库");
        //sql:alter table table_name add phone integer;
        String sql="alter table "+Constants.TABLE_NAME+" add phone integer";
        db.execSQL(sql);
    }

运行之后发现没变化,查看说明要更新版本号才会调用变化,我们此时更改写好的静态调用版本号(后台会对比,不同则正常old和new版本号进行升级)。运行发现升级的log已经打印了,刷新查看就有了,还多测试了一个sno。
在这里插入图片描述在这里插入图片描述

  1. 为了方便观察版本号更新迭代,可以加入switch(ps:用逗号隔开字段时可能会显示检查错误,不过是误报)在这里插入图片描述
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d(TAG,"升级数据库");
        //sql:alter table table_name add phone integer;
        String sql;
        switch (oldVersion){
            case 1:
                //添加address和phone字段
                 sql="alter table "+Constants.TABLE_NAME+" add  phone integer,address varchar";
                db.execSQL(sql);
                break;
            case 2:
                sql="alter table "+Constants.TABLE_NAME+" add  sno integer";
                db.execSQL(sql);
                break;
            case 3:
                sql="alter table "+Constants.TABLE_NAME+" add  address varchar";
                db.execSQL(sql);
                break;
        }
    }

2.【增删改查】

public class Dao {
    private static final String TAG ="Dao Query" ;
    private final DatabaseHelper mhelper;

    public Dao(Context context){

        //创建并拿到数据库
         mhelper= new DatabaseHelper(context);
        //helper.getWritableDatabase();
    }

    public void insert(){
        //写入
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
        String sql="insert into "+Constants.TABLE_NAME+"(_id,name,age,salary,phone,sno,address) values(?,?,?,?,?,?,?)";
        db.execSQL(sql,new Object[]{1,"Kirika",18,1,12345,"201701014145","china"});
        db.close();//关闭相关引用
    }
    public void delete(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
        String sql="delete from "+Constants.TABLE_NAME+ " where age=18";
        db.execSQL(sql);
        db.close();//关闭相关引用
    }
    public void update(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
        String sql="update "+Constants.TABLE_NAME+ " set salary=2 where age=18";
        db.execSQL(sql);
        db.close();//关闭相关引用
    }
    public void query(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
        String sql="select * from "+Constants.TABLE_NAME;
        //db.execSQL(sql); 这个方法无返回值的
        Cursor cursor= db.rawQuery(sql,null);
        while (cursor.moveToNext()){
            int index=cursor.getColumnIndex("name");
            String name=cursor.getString(index);
            Log.d(TAG,name);
            //cursor.getString(1);//获取第一列,从0开始且不含首为计数列
        }
        cursor.close();//资源型关闭
        db.close();//关闭相关引用
    }
}

3.【编写测试类】测试的好处在于每个方法都可以直接运行,先不用加入到核心代码中

  1. 新版不用继承AndroidTextCase而是
    a. 类前加上@RunWith(AndroidJUnit4.class)
    b.方法前加上 @Test
    c.Context appContext = InstrumentationRegistry.getTargetContext();获取上下文
    d.运行报错说找不了test例子,就纳闷了,后来查阅将gradle工具run test using改为IDEA重启即可。
    在这里插入图片描述
  2. 其他测试了也没问题
package com.ywjh.databasedemo;

import android.content.Context;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;

import static org.junit.Assert.assertEquals;

@RunWith(AndroidJUnit4.class)
public class TestDatabase  {
    Context appContext = InstrumentationRegistry.getTargetContext();
    @Test
    public void testCreate() {
        //测试创建数据库

    }
    @Test
    public void testInsert() {
        //测试插入数据
        //System.out.println("111");
        Dao dao=new Dao(appContext);
        dao.insert();

    }
    @Test
    public void testDelete() {
        //测试删除数据
        Dao dao=new Dao(appContext);
        dao.delete();
    }
    @Test
    public void testUpdate() {
        //测试删除数据
        Dao dao=new Dao(appContext);
        dao.update();
    }
    @Test
    public void testQuery() {
        //测试查找数据
        Dao dao=new Dao(appContext);
        dao.query();
    }
}

4.【安卓API_CRUD】sql语句较为严格,空格之类的比较麻烦,google提供封装了语法API

改写为面向对象式的,完全OK

public void insert(){
        //写入
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
       /* String sql="insert into "+Constants.TABLE_NAME+"(_id,name,age,salary,phone,sno,address) values(?,?,?,?,?,?,?)";
        db.execSQL(sql,new Object[]{1,"Kirika",18,1,12345,"201701014145","china"});*/

        ContentValues values=new ContentValues();//接着添加数据
                      values.put("_id",2);
                      values.put("name","larrpage");
                      values.put("age",18);
                      values.put("salary",23243);
                      values.put("phone",12345);
                      values.put("sno","2017023432");
                      values.put("address","china");
        db.insert(Constants.TABLE_NAME,null,values);//二参数是可否为空字段  三参数是填充内容 hashMap结构
        db.close();//关闭相关引用
    }
    public void delete(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
        /*String sql="delete from "+Constants.TABLE_NAME+ " where age=18";
        db.execSQL(sql);*/
        int result=db.delete(Constants.TABLE_NAME,null,null);//判断条件与返回值 返回为删除行数
        System.out.println("删除结果为:"+result);
        db.close();//关闭相关引用
    }
    public void update(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
       /* String sql="update "+Constants.TABLE_NAME+ " set salary=2 where age=18";
        db.execSQL(sql);*/

        ContentValues values=new ContentValues();//接着添加数据
                      values.put("phone",2222222);

        db.update(Constants.TABLE_NAME,values,null,null);//null为所有记录
        db.close();//关闭相关引用
    }
    public void query(){
        SQLiteDatabase db= mhelper.getWritableDatabase();//获取到数据库后对表进行查找
     /*   String sql="select * from "+Constants.TABLE_NAME;
        //db.execSQL(sql); 这个方法无返回值的
        Cursor cursor= db.rawQuery(sql,null);
        while (cursor.moveToNext()){
            int index=cursor.getColumnIndex("name");
            String name=cursor.getString(index);
            Log.d(TAG,name);
            //cursor.getString(1);//获取第一列,从0开始且不含首为计数列
        }
        cursor.close();//资源型关闭*/


        Cursor cursor=db.query(Constants.TABLE_NAME,null,null,null,null,null,null);
        while (cursor.moveToNext()){
            int id=cursor.getInt(0);
            String name=cursor.getString(1);
            Log.d(TAG,"id=="+id+" name"+name);
        }
        cursor.close();
        db.close();//关闭相关引用
    }

5.【数据库事务Transcation】安全性与高效性

1.情景

  1. 每月15号,公司发工资,财务有100000,要-1200,你的账号+1200,此时停电了,公司减了,但账号未增加

2. 测试安全性编码

  1. 创建安卓项目后再次新建类继承SQLiteOpenHelpter,写个构造方法用于初始化
public class DatabaseHelpter extends SQLiteOpenHelper {
    public DatabaseHelpter(Context context) {
        super(context,"account.db", null, 1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table account(_id integer,name varchar,money integer)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

  1. 编写测试类
    1)完成数据库构造方法创建数据库并且伴生oncreate()创建Account表,接着测试插入和更新(流程都是通过创建的Helpter对象返回的对应数据库,然后获取对应权限,返回权限对象,通过对象进行sql操作)

@RunWith(AndroidJUnit4.class)
public class TestDataBase {
    Context appContext = InstrumentationRegistry.getTargetContext();
    @Test//用于执行创建的方法
    public void testDataBase(){
        //测试数据库创建
        System.out.println("1111111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        helpter.getReadableDatabase();
    }

    @Test
    public void testInsert() {
        //测试插入数据的方法
        //System.out.println("111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        SQLiteDatabase db=helpter.getReadableDatabase();
        db.execSQL("insert into account values(1,'tony',100000)");
        db.execSQL("insert into account values(2,'myc',0)");
        db.close();
    }

    @Test
    public void testUpdate() {
        //测试插入更新数据的方法
        //System.out.println("111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        SQLiteDatabase db=helpter.getReadableDatabase();
        db.execSQL("update account set money = 100000-1200 where name= 'tony'");
        //人为模拟一次异常 发现只执行了第一句
        int i=10/0;//分母为0出异常
        db.execSQL("update account set money =1200 where name= 'myc'");
    }
}

执行后发现人为中断前的操作都执行了
在这里插入图片描述

  1. 改写update,加入try-catch与事务套餐
 @Test
    public void testUpdate() {
        //测试插入数据
        //System.out.println("111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        SQLiteDatabase db=helpter.getReadableDatabase();
        db.beginTransaction();
        //人为模拟一次异常 发现只执行了第一句
        try{
            db.execSQL("update account set money = 100000-600 where name= 'tony'");
            int i=10/0;//分母为0发生异常
            db.execSQL("update account set money =1200 where name= 'myc'");
            db.setTransactionSuccessful();
        }catch(Exception e){
            //处理异常
           throw new RuntimeException("停电了");
        }finally {
            db.endTransaction();
            db.close();
        }

    }

这里我们修改了中断前的操作,运行发现中断前后都不执行,数据库不变
在这里插入图片描述

3.测试高效性编码

  1. 修改insert,使其插入6000条数
 @Test
    public void testInsert() {
        //测试插入数据
        //System.out.println("111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        SQLiteDatabase db=helpter.getReadableDatabase();

        long start=System.currentTimeMillis();
        for(int i=0;i<3000;i++){
            db.execSQL("insert into account values(1,'company',200000)");
            db.execSQL("insert into account values(2,'my_count',0)");
        }
        Log.d(TAG,"usetime =="+(System.currentTimeMillis()-start));
        System.out.println("使用时间为:"+(System.currentTimeMillis()-start));

  /*      db.execSQL("insert into account values(1,'tony',100000)");
        db.execSQL("insert into account values(2,'myc',0)");*/
        db.close();
    }
  1. 开启事务,十分高效开启和关闭,十分简洁。 原理是:
    a:原操作是打开数据库,插入数据,关闭数据库(耗时较多)
    b:运用事务:将数据存入存,通过内存写入,同目录下的journay就是防止文件过大而生成的temp文件。
@Test
    public void testInsert() {
        //测试插入数据
        //System.out.println("111");
        DatabaseHelpter helpter=new DatabaseHelpter(appContext);
        SQLiteDatabase db=helpter.getReadableDatabase();

        long start=System.currentTimeMillis();
        db.beginTransaction();
        for(int i=0;i<3000;i++){
            db.execSQL("insert into account values(1,'company',200000)");
            db.execSQL("insert into account values(2,'my_count',0)");
        }
        db.endTransaction();
        Log.d(TAG,"usetime =="+(System.currentTimeMillis()-start));
        System.out.println("事务使用时间为:"+(System.currentTimeMillis()-start));

  /*      db.execSQL("insert into account values(1,'tony',100000)");
        db.execSQL("insert into account values(2,'myc',0)");*/
        db.close();
    }

下面是对比图
在这里插入图片描述
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章