前面所学的文件存储和SharedPreferences存储只适用用于保存一些见到那的数据,当需要存储大量复杂的关系型数据库的时候,这两种存储方式就不行了,下面介绍SQLite数据库
创建数据库
Android中提供了一个SQLiteOpenHelper帮助类,借助个类就可以非常简单的对数据库进行操作
- 要知道SQLiteOpenHelper是一个抽象类,要使用它就必须自己定义一个类继承它,必须还的重写两个方法,onCreate()和onUpgtade(),然后分别在这两个方法中去实现创建,升级数据库的逻辑
- SQLiteOpenHelper中还有两个非常重要的实例方法,相同的是都可以创建或者打开一个现有的数据库,如果数据库已经存在的就直接打开,没有存在就新建一个数据路,并返回一个可以对数据库进行读写操作的对象,不同的是当数据库不可写入的时候(磁盘空间满)
- getReadableDatabese()返回的对象将以只读的方式去打开数据库
- getWritableDatabase()方法则会出现异常
- SQLiteOpenHelper中有两个构造方法可以重写,一般使用参数少的那个构造函数,这个构造方法接收四个参数,
- 第一个参数是Context,必须要有它才能对数据库进行操作,
- 第二个参数数据库名,创建数据库时使用的就是这个参数指定名称
- 第三个参数允许我们在查询数据的时候返回一个自定义的Cursor,一般传入的unll
- 第四个参数表示当前的数据库版本号,可以用于对数据库进行升级操作
构建SQLiteOpenHelper的实例后,在调用getReadableDatabese()或者getWritableDatabase()方法就可以创建数据库了,数据库的文件会放在/data/data/<package name>/databases/目录下,此时重写的onCreate()方法就会得到执行,在这去处理一些创建表的逻辑
- 在代码中实现,在MyDatabaseHelper类中继承SQLiteOpenHelper
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 mContent;
// 重写构造方法,接收四个参数
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContent = context;
}
// 创建数据库
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// 调用方法
sqLiteDatabase.execSQL(CREATE_BOOK);
Toast.makeText(mContent,"创建成功",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
- 这里把建表的语句定义成一个字符串,然后onCreate()方法中通过execSQL()创建表
- 修改activity_main.xml中的代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/carete_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database"/>
</LinearLayout>
- 点击这个按钮的时候就会创建一个数据库
- 在MainActivity中
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取到这个类的对象
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,1);
Button createDatabese = (Button)findViewById(R.id.carete_database);
createDatabese.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击按钮的时候就创建这个数据库
dbHelper.getWritableDatabase();
}
});
}
}
-
获取到自定类的对象,数据库名为BookStore.db,版本为1,第一次点击的时候,先创建数据库,再创建表
-
问题来了,该怎么查看呢,这个时候我们使用adb shell进行查看,adb在sdk/platform-tools目录下,把它添加到path环境中
-
环境配置好后,打开命令行,输入adb shell进入(我是用夜神进入的)
然后使用cd命令进入到/data/data/项目名/databases/目录下,然后使用ls命令查看到该目录中的文件
这个时候,这个目录下出现了两个数据库,一个就是创建的BookStore.db,另一个就是一个临时的日志文件,借助sqlite命令打开数据库,输入sqlite3,然后后面加上数据库名
这个时候已经打开了BookStore.db数据库,现在就可以对这个数据库进行管理了,查看当前的数据库中有那些表,输入.table命令
-
此时数据库中会有两个表,一个android_metadata表是每个数据库中都自动生成的,另一个就是我们自己创建的,可以通过.schema命令来查看他们的建表语句,.exit退出上一层
升级数据库
这个时候你会发现,在MyDatabaseHelper中还有一个空方法,就是onUpgrade()方法用于对数据库进行升级,
- 这个时候,如果想要添加一个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 mContent;
// 重写构造方法,接收四个参数
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContent = context;
}
// 创建数据库
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
// 调用方法
sqLiteDatabase.execSQL(CREATE_BOOK);
// 再创建一个表
sqLiteDatabase.execSQL(CREATE_CATEGORY);
Toast.makeText(mContent,"创建成功",Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
- 这个时候又通过字符串的方法新建了一个表,运行程序,这个时候你会发现并没有弹创建成功,这是为什么呢?
- 因为数据库已经存在了,而onCreate()方法就不会得到执行了,所有第二个就会创建不成功
- 这个时候就该使用onUpgrade()方法了,利用它进行数据库的升级,在MyDatabaseHelper中
public class MyDatabaseHelper extends SQLiteOpenHelper {
//和上面一样
...
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
sqLiteDatabase.execSQL("drop table if exists Book");
sqLiteDatabase.execSQL("drop table if exists Category");
onCreate(sqLiteDatabase);
}
}
- 在这个方法中,执行了两条DROP语句,如果发现数据库中存在Book表和Catagory表,就把这两个表删除掉,再调用onCreate()方法重新创建
- 这里先把已经存在的表删除掉,因为如果创建的时候发现这个表存在的话,就会报错
- 接下来就是怎么让这个方法执行,还记得在SQLiteOpenHelper的构造方法中接收的第四个参数,它代表当前的版本号,之前传入的是1,此时传入一个比1大的数字,就可以让这个onUpgrade()方法得到执行了
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取到这个类的对象,此时把版本号改成2
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
Button createDatabese = (Button)findViewById(R.id.carete_database);
createDatabese.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击按钮的时候就创建这个数据库
dbHelper.getWritableDatabase();
}
});
}
}
-
版本号指定为2,表示对数据库进行升级,运行程序,这个时候还是使用上面的命令进行查看
添加数据
对数据表中的数据操作无非有四种,增删查改,和sql一样,前面说getReadableDatabese()或者getWritableDatabase()方法可以用于创建和升级数据库,但是这两个方法都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行增删查改
- 增,使用insert()方法,它接收3个参数,第一个参数是表名,第二个参数用于在末指定添加数据的情况下给某些可为空的列自动赋值NULl,一般不用,直接传入null,第三个参数是ContentValues对象,它提供了一些put()方法重载,用于向ContentValues中添加数据,只需将表中的每个列名以及相应的待添加数据传入即可
修改activity.xml代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"/>
</LinearLayout>
- 新增一个按钮,用于添加数据
在MainActivity中修改代码
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
......
Button addData = (Button)findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name","The Da Vinci Code");
values.put("author","Dan Brown");
values.put("pages","454");
values.put("price","17.89");
// 插入进去
db.insert("Book",null,values);
values.clear();
// 开始组装第二条数据
values.put("name","The Lost Symbol");
values.put("author","Dan Brown");
values.put("pages","890");
values.put("price","175.89");
db.insert("Book",null,values);
}
});
}
}
- 添加点击事件,先获取SQLiteDatabase对象,然后使用ContentValues来对进行添加的数据进行组装,调用insert()方法把数据插入到表中,这里添加了两条数据
-
运行程序,点击按钮,进入到数据库中,最后有;号
更新数据
会添加后,还有对数据进行更新,使用updata()方法,这个方法接收四个参数,第一个还是表名,第二个是ContentValues对象,把要更新的数据组装进去,第三、第四参数用于约束更新莫一行或者某几行的数据,不指定的话就是默认更新所有的
- 还是在上面的基础上进行修改
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
...
<Button
android:id="@+id/updata_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Updata data"/>
</LinearLayout>
- 给这个按钮添加绑定事件用于更改数据
- 在MainActivity中
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
Button updataData = (Button)findViewById(R.id.updata_data);
updataData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",100);
db.update("Book",values,"name = ?",new String[]{"The Da Vinci Code"});
}
});
}
}
- 这里调用了updata()方法执行具体的操作,在第三个,第四个参数来指定更新的具体行数,第三个参数是对应的where部分,表示更新所有的name等于?的,而?是一个占位符,通过第四个参数提供的字符串数组作为第三个参数的占位符指定相应的内容,就是把名字等于The Da Vinci Code的价格改成100
- 运行程序,点击按钮
-
输入命令进行查看
可以看到名字为The Da Vinci Code的价格都是100
删除数据
使用的是delete()方法,第一个参数还是表名,第二个、第三个参数用于约束删除某一行或者莫几行的数据,不指定的话默认删除所有的行
- 修改acticity.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
...
<Button
android:id="@+id/dalete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"/>
</LinearLayout>
- 在MainActivity中
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
// 删除数据
Button deleteData = (Button)findViewById(R.id.dalete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book","price = ?",new String[]{"100"});
}
});
}
}
- 这里只当price等于100的删除掉
-
运行程序,点击删除按钮
-
查看数据库中的数据
查询数据
这个是最复杂的一个操作,使用的是query()方法,最短的一个方法重载也要传入7个参数、
但是多数的情况下只需要传入几个参数就可以了,调用query()方法后会返回一个Cursor对象,查询到的所有数据都将从这个对象中取出
- 在activity_main.xml中
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<Button
android:id="@+id/carete_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Create database"/>
<Button
android:id="@+id/add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add data"/>
<Button
android:id="@+id/updata_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Updata data"/>
<Button
android:id="@+id/dalete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Delete data"/>
<Button
android:id="@+id/query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Query data"/>
</LinearLayout>
- 添加按钮用于查询数据,
- 修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper dbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 获取到这个类的对象 数据库建立
dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);
final Button createDatabese = (Button)findViewById(R.id.carete_database);
createDatabese.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 点击按钮的时候就创建这个数据库
dbHelper.getWritableDatabase();
}
});
// 添加一条数据
Button addData = (Button)findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name","The Da Vinci Code");
values.put("author","Dan Brown");
values.put("pages","454");
values.put("price","17.89");
// 插入进去
db.insert("Book",null,values);
values.clear();
// 开始组装第二条数据
values.put("name","The Lost Symbol");
values.put("author","Dan Brown");
values.put("pages","890");
values.put("price","175.89");
db.insert("Book",null,values);
Toast.makeText(MainActivity.this,"aaaaaa",Toast.LENGTH_SHORT).show();
}
});
// 更新一条数据
Button updataData = (Button)findViewById(R.id.updata_data);
updataData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",100);
db.update("Book",values,"name = ?",new String[]{"The Da Vinci Code"});
}
});
// 删除数据
final Button deleteData = (Button)findViewById(R.id.dalete_data);
deleteData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book","price = ?",new String[]{"100"});
}
});
// 查询数据
Button queryButton = (Button)findViewById(R.id.query_data);
queryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = dbHelper.getWritableDatabase();
// 查询Book表中的所有数据
Cursor cursor = db.query("Book",null,null,null,null,null,null);
if(cursor.moveToFirst()){
do{
// 遍历Cursor对象,取出数据并打印
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 author is "+author);
Log.d("Mainactivity","book pages is "+pages);
Log.d("Mainactivity","book price is "+price);
}while (cursor.moveToNext());
}
// 最后记着关闭
cursor.close();
}
});
}
}
- 运行程序,点击按钮,可以看到
- 当然了,这只是一个最简单的例子
直接使用SQL操作数据库,
除了查询使用的是rawQuery()方法,其他的操作都是调用execSQl()方法,操作的结果和上面演示的一行,对SQL熟练的话,可以使用这种操作,更加的方便