6.4 SQLite数据库存储
SQLite是一种轻量级的关系型数据库,运算速度快,占用资源少。
6.4.1 创建数据库
Android为了管理数据库,专门提供了SQLiteOpenHelper帮助类,借助这个类可以对数据库进行创建和升级。
SQLiteOpenHelper是一个抽象类,需要创建一个自己的帮助类去继承它。
SQLiteOpenHelper有两个抽象方法,onCreate()和onUpgrade(),分别实现创建、升级数据库的逻辑。
SQLiteOpenHelper的另外两个重要的实例方法:getReadableDatabases()和getWritableDatabases(),这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在在则直接打开,否则则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。当数据库不可写入时(如磁盘已满),getReadableDatabases()方法返回额对象将以只读方式去打开数据库,而getWritable DATabase()方法则出现异常。
a. 新建MyDatabaseHelper类继承SQLiteOpenHelper
SQLiteOpenHelper的构造方法接收四个参数,第一个为Context,第二个为参数为数据库名,第三个为允许在查询数据的时候返回一个自定义的Cursor,一般为null,第四个表示当前数据库的版本号,用于对局库进行升级操作。
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book(" +"id integer primary key autoincrement, " +"author text, " +"price real, " +"pages integer, " +"name text)"; private Context mContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){ super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
b. 布局中加一个button
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/create_database" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Create database"/> </LinearLayout>
c.在MainActivity中给Button注册事件来创建数据库
构建出SQLiteOpenHelper的实例之后,调用.getWritableDatabase()方法
public class MainActivity extends AppCompatActivity { private MyDatabaseHelper dpHelper; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dpHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1); Button createDatabase = (Button) findViewById(R.id.create_database); createDatabase.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dpHelper.getWritableDatabase(); } }); }
运行程序:
点击按钮就会显示Toast,并创建数据库。
6.4.2 升级数据库
添加一张Category()表
public class MyDatabaseHelper extends SQLiteOpenHelper { public static final String CREATE_BOOK = "create table Book(" +"id integer primary key autoincrement, " +"author text, " +"price real, " +"pages integer, " +"name text)"; public static final String CREATE_CATEGORY = "create table CATEGORY(" +"id integer primary key autoincrement, " +"category_name text, " +"category_code integer)"; private Context mContext; public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version){ super(context, name, factory, version); mContext = context; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(CREATE_BOOK); db.execSQL(CREATE_CATEGORY); Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("drop table if exists Book"); db.execSQL("drop table if exists Category"); onCreate(db); } }
在onUpgrade()方法中执行了两条DROP语句,如果发现数据库中已经存在Book表或Category表了,就将两张表删除掉,然后再调用onCreate()方法重建。
需要先将已经存在的表删除掉,若在创建时发现这张表已经存在了,就会直接报错。
在MainActivity中修改代码
dpHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
将版本号改为比1大的数即可,表明对数据库进行升级了。
在adb shell 中打开BookStore.db 数据库
表明创建了Book和Category
6.4.3 添加数据
对数据进行的操作有4种,CRUD,添加(Create),查询(Retrieve),更新(Update),删除(Delete)
SQL语言中,添加数据 insert,查询数据 select,更新数据 update,删除 delete
SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()方法都会返回一个SQLiteDatabase对象,借助这个对象进行所有的CRUD操作。
添加操作
SQLiteDatabase提供了一个insert()方法来添加数据,接收三个参数,第一个为表的名字,第二个用于在未指定添加数据的情况下给某些可为空的列自动赋值null,一般直接传入null,第三个参数是一个ContentValues对象,提供了一系列的put()方法重载,用于向ContentValues中添加数据,每个列名以及对应的待添加数据传入即可。
a.加一个button,用于添加数据
<Button android:id="@+id/add_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Add data"/>
b.修改MainActivity中的代码
Button addData = (Button) findViewById(R.id.add_data); addData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dpHelper.getWritableDatabase(); ContentValues values = new ContentValues(); //组装第一条数据 values.put("name", "The Da Vinci Code"); values.put("author","Dan Brown"); values.put("pages",454); values.put("price",16.96); db.insert("Book", null, values);//插入第一条数据 values.clear(); values.put("name", "The Lost Symbol"); values.put("author","Dan Brown"); values.put("pages",510); values.put("price",19.95); db.insert("Book", null, values); Toast.makeText(MainActivity.this, "Add successfully", Toast.LENGTH_SHORT).show(); } });
运行程序:
点击按钮两次
6.4.4 更新数据
SQLiteDatabase提供了update()方法,接收4个参数。
第一个为表明,第二个是ContentValues对象,把更新的数据在这里装进去。第三、第四个参数用于约束更新某一行或某几行的数据,不指定的话默认就是更新所有行。
a.添加一个button用于更新数据
<Button android:id="@+id/update_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Update data"/>
b.修改MainActivity中的代码
Button updateData = (Button) findViewById(R.id.update_data); updateData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dpHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("price", 10.99); db.update("Book", values, "name = ?", new String[]{"The Da Vinci Code"}); } });
value.put("price", 10.99) 表示把价格这一列的数据更新成10.99
update的第三个参数对应的是SQL语句的where部分,表明更新所有name等于?的行,而?是一个占位符,通过第四个参数提供的一个字符串数组为第三个参数中的每个占位符指定相应的内容,意图即为name为The Dat Vinci Code的价格改为10.99
可以看到The Da Vinci Code价格都更新为10.99
6.4.5 删除数据
SQLiteDatabase中提供了delete()方法,接收三个参数。
第一个为表名,第二、第三个参数用于约束删除每一行或某几行的数据,不指定的话默认删除所有。
a.加一个Button,用于删除表中数据
<Button android:id="@+id/delete_data" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Delete data"/>
b.修改Mainactivity中的代码
Button deleteData = (Button)findViewById(R.id.delete_data); deleteData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dpHelper.getWritableDatabase(); db.delete("Booke", "pages > ?", new String[]{"500"}); Toast.makeText(MainActivity.this, "Delete successfully", Toast.LENGTH_SHORT).show(); } });
第二、第三个参数意思是从表中删除页数大于500的书
运行程序:
发现大于500页的书都已经从表中消失。
6.4.6 查询数据
SQL = Structured Query Language 结构化查询语言,主要功能体现在“查”上
SQLiteDataBase提供了query()方法用于对数据查询,最短的重载需要传入七个元素
query()方法参数 | 对应SQL部分 | 描述 |
table | from table_name | 指定查询的表名 |
columns | select column1, column2 | 指定查询的列名 |
selection | where column = value | 指定where的约束条件 |
selectionArgs | - | 为where中的占位符提供具体的值 |
groupBy | group by column | 指定需要group by的列 |
having | having column = value | 对group by后的结果进行进一步约束 |
orderBy | order by column1, comlumn2 | 指定查询结果的排序方式 |
在布局中加入Button query data
1 <Button 2 android:id="@+id/query_data" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:text="Query Data"/>
修改MainAvtivity中的代码
Button queryData = (Button)findViewById(R.id.query_data); queryData.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { SQLiteDatabase db = dpHelper.getWritableDatabase(); //查询Book表中所有的数据 Cursor cursor = db.query("Book", null, null, null, null, null, null); if(cursor.moveToFirst()){ do{ String name = cursor.getString(cursor.getColumnIndex("name")); String author = cursor.getString(cursor.getColumnIndex("author")); int pages = cursor.getInt(cursor.getColumnIndex("pages")); double price = cursor.getDouble(cursor.getColumnIndex("price")); Log.d("MainActivity", "book name is " + name); Log.d("MainActivity", "book authur is " + author); Log.d("MainActivity", "book page is " + pages); Log.d("MainActivity", "book price is " + price); }while(cursor.moveToNext()); } cursor.close(); } });