Use of Android SQLite

I would like to record the learning process with articles, and please indicate if there are any mistakes.

foreword

There are many ways to store data in Android, and SQLite is one of them. Saving data to a database is ideal for repetitive or structured data, such as contact information. This article will also start to introduce the basic use of SQLite. If you find it difficult to read this article, please first understand the basic use of SQL statements.

Features of SQlite

  • Lightweight
    SQLite is different from database software in C/S mode. It is an in-process database engine, so there is no database client and server. Using SQLite generally only needs to bring one of its dynamic libraries to enjoy all its functions

  • Single file The
    so-called "single file" means that all the information in the database (such as tables, views, triggers, etc.) is contained in one file. This file can be copied to other directories or other machines, and it can be used correctly.

  • Cross-platform
    Support mainstream operating systems, as well as Android, WindowsMobile and other systems

  • The in- memory database
    SQLite API does not distinguish whether the currently operating database is in memory or in a file (transparent to the storage medium).

Use of SQLite

  • Defining Schema and Contract
    Usually, we create a "contract" class Contractto help us define the schema of the database, and in this class, we create an anonymous class for each table in the database and add member properties to store the properties of the table.

    An example is as follows:

//创建"契约"类,存放数据库各个表,及其相关属性
public class Contract {

    //私有化,防止意外的实例化此类
    private Contract() {
    }
    //为User表创建一个匿名类,声明其中属性
    public static class User {
        public static final String TABLE_NAME = "user";
        public static final String COLUMN_ID = "id";
        public static final String COLUMN_NAME = "name";
    }
}
  • Custom-created subclasses of SQLiteOpenHelper The
    SQLiteOpenHelperclass contains a useful set of classes for managing databases api. When using this class to obtain a reference to the database, the class performs internal custom operations, which are only done during database creation and updating, not during application startup. This class exists so that all we need to do is call getWritableDatabase()or getReadableDatabase().

    An example is as follows:

public class DatabaseHelper extends SQLiteOpenHelper {

    private static final String TAG = "DatebaseHelper";

    //数据库版本
    private static final int DATABASE_VERSION = 1;
    //数据库名称
    private static final String DATABASE_NAME = "whd_db";

    //组装创建表的SQL语句
    private static final String SQL_CREATE =
            "create table " + Contract.User.TABLE_NAME + " ( " +
                    Contract.User.COLUMN_ID + " integer primary key," +
                    Contract.User.COLUMN_NAME + " text)";

    //组装删除表的语句,一般用于升级数据库时,删除已有的表,防止无法更新数据库
    private static final String SQL_DELETE=
            "DROP TABLE IF EXISTS " + Contract.User.TABLE_NAME;

    //构造函数,必须有
    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }
    //context:上下文对象
    //name:数据库名称
    //param:factory
    //version:当前数据库版本,值递增

    //第一次创建数据库时调用
    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.d(TAG, "onCreate: "+ "创建数据库和表");
        //执行sql语句
        db.execSQL(SQL_CREATE);

    }

    //升级数据库时调用(数据库版本发生变化时)
    //数据库版本只能递增!
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL(SQL_DELETE);
        onCreate(db);
        Log.d(TAG, "onUpgrade: "+ "更新数据库,当前版本号:" + newVersion);
    }
}
  • Create database & operate database

    Create:SQLiteOpenHelper The encapsulation makes it extremely simple for us to create a database. We only need to SQLiteOpenHelperinstantiate the object of the subclass, and then call getWritableDatabase()or getReadableDatabase()to get a reference to the database.

    Operation: : The operation of the database is nothing more than CRID (Add, Delete, Modify and Check).

    We won't say more, the comments in the example are very detailed:


public class SQLiteActivity extends AppCompatActivity implements View.OnClickListener {

    private DatabaseHelper helper;
    private SQLiteDatabase database;
    private static int VERSION = 1;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sqlite);
        //初始化
        initViews();
        //创建DatebaseHelp对象,传入context
        helper = new DatabaseHelper(this);

    }
    //初始化按钮组件,设置监听
    private void initViews(){
        findViewById(R.id.createDatabase).setOnClickListener(this);
        findViewById(R.id.insert).setOnClickListener(this);
        findViewById(R.id.delete).setOnClickListener(this);
        findViewById(R.id.update).setOnClickListener(this);
        findViewById(R.id.query).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            //创建数据库
            case R.id.createDatabase:
                helper.getWritableDatabase();
                break;
            //插入数据
            case R.id.insert:
                database = helper.getWritableDatabase();
                //通过ContentValues对象,以键值对的方式存储
                ContentValues values = new ContentValues();
                values.put(Contract.User.COLUMN_ID,1);
                values.put(Contract.User.COLUMN_NAME,"whdalive");
                //插入数据到数据库
                database.insert(Contract.User.TABLE_NAME,null,values);
                // 参数1:要操作的表名称
                // 参数2:SQl不允许一个空列,若ContentValues是空,那么这一列被明确的指明为NULL值
                // 参数3:ContentValues对象

                //用完关闭数据库
                database.close();
                //或者通过的execSQL(),再里面直接输入SQL语句
                //不过缺点在于可能被恶意SQL注入
                //database.execSQL("insert into user values(?,?)",new String[]{String.valueOf(2),"whdalive"});
                //Android studio 3.0上会提示(?,?)部分有错误,但是实际编译没问题,不知道是什么原因
                break;
            //删除数据
            case R.id.delete:
                database = helper.getWritableDatabase();
                String selection = Contract.User.COLUMN_ID + " = ?";
                String[] selectionArgs = {String.valueOf(1)};
                database.delete(Contract.User.TABLE_NAME,selection,selectionArgs);
                // 参数1:表名(String)
                // 参数2:WHERE表达式(String),需删除数据的行; 若该参数为 null, 就会删除所有行;?号是占位符
                // 参数3:WHERE选择语句的参数(String[]), 逐个替换 WHERE表达式中 的“?”占位符;


                //database.execSQL("delete from user where id = ?",new String[]{String.valueOf(1)});
                database.close();
                break;
            //更新数据
            case R.id.update:
                database = helper.getWritableDatabase();
                ContentValues values1 = new ContentValues();
                values1.put(Contract.User.COLUMN_NAME,"chuang");
                String selection1 = Contract.User.COLUMN_ID + " = ?";
                String[] selectionArgs1 = {String.valueOf(1)};
                database.update(Contract.User.TABLE_NAME,values1,selection1,selectionArgs1);
                // 参数1:表名(String)
                // 参数2:需修改的ContentValues对象
                // 参数3:WHERE表达式(String),需数据更新的行; 若该参数为 null, 就会修改所有行;?号是占位符
                // 参数4:WHERE选择语句的参数(String[]), 逐个替换 WHERE表达式中 的“?”占位符;

                //database.execSQL("update user set name = ? where id = ?", new String[]{String.valueOf(1),"chuang"});
                database.close();
                break;
            //查询数据
            case R.id.query:
                database = helper.getWritableDatabase();
                String[] projection = {Contract.User.COLUMN_ID, Contract.User.COLUMN_NAME};
                Cursor cursor = database.query(Contract.User.TABLE_NAME,projection,null,null,null,null,null);
                // 参数说明
                // table:要操作的表
                // columns:查询的列所有名称集
                // selection:WHERE之后的条件语句,可以使用占位符
                // groupBy:指定分组的列名
                // having指定分组条件,配合groupBy使用
                // orderBy指定排序的列名
                // limit指定分页参数
                // distinct可以指定“true”或“false”表示要不要过滤重复值

                //SQL输入方式
                //Cursor cursor = database.rawQuery("select * from user",null);
                while (cursor.moveToNext()){
                    String name = cursor.getString(cursor.getColumnIndex(Contract.User.COLUMN_NAME));
                    int id = cursor.getInt(cursor.getColumnIndex(Contract.User.COLUMN_ID));
                    Log.d("11111", "查询结果: id:"+id+" name: " + name );
                }
                /*Cursor对象常用方法如下:
                cursor.move(int offset); //以当前位置为参考,移动到指定行
                cursor.moveToFirst();    //移动到第一行
                cursor.moveToLast();     //移动到最后一行
                cursor.moveToPosition(int position); //移动到指定行
                cursor.moveToPrevious(); //移动到前一行
                cursor.moveToNext();     //移动到下一行
                cursor.isFirst();        //是否指向第一条
                cursor.isLast();     //是否指向最后一条
                cursor.isBeforeFirst();  //是否指向第一条之前
                cursor.isAfterLast();    //是否指向最后一条之后
                cursor.isNull(int columnIndex);  //指定列是否为空(列基数为0)
                cursor.isClosed();       //游标是否已关闭
                cursor.getCount();       //总数据项数
                cursor.getPosition();    //返回当前游标所指向的行数
                cursor.getColumnIndex(String columnName);//返回某列名对应的列索引值
                cursor.getString(int columnIndex);   //返回当前行指定列的值
                */

                cursor.close();
                database.close();
                break;
        }
    }
}

Summarize

  • This article summarizes the use of SQLite in Android, and I will introduce the use of the ROOM framework later.
  • The author's level is limited, if there are any mistakes or omissions, please correct me.
  • Next, I will also share the knowledge I have learned. If you are interested, you can continue to pay attention to the Android development notes of whd_Alive.
  • I will share technical dry goods related to Android development from time to time, and look forward to communicating and encouraging with you.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326073036&siteId=291194637