(一)使用Android原生API
1. 介绍
-
SQLite是D.Richard Hipp用C语言编写的开源嵌入式数据库引擎,它是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它的设计目标是嵌入式的,而且由于其占用资源低(占用内存只需几百K)、处理速度快等特点,目前许多嵌入式产品中都使用了它,其中就包括大名鼎鼎的iOS和Android移动操作系统。SQLite能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月, 至今已经有14个年头,现在SQLite也迎来了一个版本 SQLite 3已经发布。SQLite的特点大致总结如下:
- 1.轻量级
使用 SQLite 只需要带一个动态库,就可以享受它的全部功能,而且那个动态库的尺寸想当小。
- 2.独立性
SQLite 数据库的核心引擎不需要依赖第三方软件,也不需要所谓的“安装”。
- 3.隔离性
SQLite 数据库中所有的信息(比如表、视图、触发器等)都包含在一个文件夹内,方便管理和维护。
- 4.跨平台
SQLite 目前支持大部分操作系统,不至电脑操作系统更在众多的手机系统也是能够运行,比如:Android和IOS。
- 5.多语言接口
SQLite 数据库支持多语言编程接口。
- 6.安全性
SQLite 数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但只能有一个可以写入数据。
-
要想了解更多有关SQLite数据库相关的历史、特点及命令操作,可以学习以下两个网站的资源:
-
http://www.sqlite.org/lang.html
-
http://www.w3cschool.cc/sqlite/sqlite-intro.html
-
2. 使用adb shell对数据库和表的创建情况进行检查
配置环境
adb是Android SDK中自带的一个调式工具,它存放在sdk的platform-tools目录下,如果想在命令行中使用这个工具,就需要先把它的路径配置到环境变量中。
-
windows系统下配置,(如果你们的系统是MAC或Linux系统,请自行百度)
- 1.找到
sdk下的platform-tools文件夹路径。

- 2.将路径配置到
Path中

- 3.配置好环境变量之后,就可以使用adb工具了。打开命令行界面(如果是
夜神模拟器看下面截图步骤)输入adb shell就会进入设备的控制台。

- 1.找到
3. 创建数据库(解释都在注释中)
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 mContext;
/**
* 在继承SQLiteOpenHelper这个类的时候有两个构造函数可供重写,一般使用参数少一点的那个构造方法即可。
* <p>
* 第一个参数:Context上下文
* 第二个参数:数据库的名字,创建数据库时使用的就是这里指定的名称
* 第三个参数:允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null
* 第四个参数:当前数据库的版本号
*
* @param context
* @param name
* @param factory
* @param version
*/
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_BOOK);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
private MyDatabaseHelper mDbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
Button createDatabase = findViewById(R.id.create_database);
createDatabase.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/**
* getWritableDatabase()和getReadableDatabase()方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否咋创建一个新的数据库)并返回一个可对数据库进行读写操作的对象。
* 不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,
* getWritableDatabase()方法则将出现异常。
*
* 数据库的文件会存放到/data/data/<package name>/database/目录下
*
*/
mDbHelper.getWritableDatabase();
}
});
}
}
4. 升级数据库
MyDatabaseHelper类中添加下面的代码
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;
/**
* 在继承SQLiteOpenHelper这个类的时候有两个构造函数可供重写,一般使用参数少一点的那个构造方法即可。
* <p>
* 第一个参数:Context上下文
* 第二个参数:数据库的名字,创建数据库时使用的就是这里指定的名称
* 第三个参数:允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null
* 第四个参数:当前数据库的版本号
*
* @param context
* @param name
* @param factory
* @param version
*/
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_BOOK);
sqLiteDatabase.execSQL(CREATE_CATEGORY);
Toast.makeText(mContext, "创建成功!", Toast.LENGTH_SHORT).show();
}
/**
* onUpgrade()方法进行数据库升级
*
* @param sqLiteDatabase
* @param i
* @param i1
*/
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
// 如果发现数据库中已经存在Book表或Category表了,就将这两张表删除掉,然后再调用onCreate()方法重新创建
// 如果不添加下面两行语句,在运行程序的时候会报错
sqLiteDatabase.execSQL("drop table if exists Book");
sqLiteDatabase.execSQL("drop table if exists Category");
onCreate(sqLiteDatabase);
}
}
MainActivity
**只需要 new MyDatabaseHelper(this, "BookStore.db", null, 2);改变最后一个参数(version),之前我们传入的是1,现在只要传入一个比1大的数就行,既可以让onUpgrade()方法得到执行了 **
5. CRUD
添加数据
主要使用了
ContentValues对象,使用insert()方法,在MainActivity中添加以下代码
Button addData = findViewById(R.id.add_data);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
// 开始组装第一条数据
values.put("name", "WangXiaoNao");
values.put("author", "Tom");
values.put("pages", 454);
values.put("price", 20.22);
// 插入第一条数据
// insert():方法,它接受3个参数,
// 第一个参数:表名。
// 第二个参数:用于未指定添加数据的情况下给某些可为空的列自动赋值NULL,一般我们用不到,直接传入null
// 第三个参数:是一个ContentValues对象,它提供了一系列的put()方法重载,用于向ContentValues中添加数据,只需要将表中的每个列名以及相应的待添加数据传入即可。
db.insert("Book", null, values);
values.clear();
// 开始组装第二条数据
values.put("name", "WangDaNao");
values.put("author", "Amry");
values.put("pages", 520);
values.put("price", 12.11);
db.insert("Book", null, values);
}
});
更新数据
使用
update()方法,在MainActivity中添加以下代码
SQLiteDatabase db1 = mDbHelper.getWritableDatabase();
ContentValues values1 = new ContentValues();
values1.put("price", 10.99);
/*
update()方法:
第一个参数:指定的表名
第二个参数:是ContentValues对象
第三个参数:对应的是SQL语句的where语句,表示更新所有name等于?的行,而?是一个占位符
第四个参数:提供一个字符串数组为第三个参数中的每个占位符指定相应的内容。
*/
db1.update("Book", values1, "name = ?", new String[]{"WangXiaoNao"});
删除数据
使用
delete()方法,在MainActivity中添加以下代码
SQLiteDatabase db2 = mDbHelper.getWritableDatabase();
/*
delete()方法:
第一个参数:表名
第二个参数、第三个参数:第二个参数相当于sql语句的where。第三个值相当于where的值。
用于约束删除某一行或某几行的数据,不指定的话默认就是删除所有行。
*/
db2.delete("Book", "pages > ?", new String[]{"500"});
查询数据
使用
query()方法,在MainActivity中添加以下代码
SQLiteDatabase db3 = mDbHelper.getWritableDatabase();
// 查询Book表中所有的数据
Cursor cursor = db3.query("Book", null, null, null, null, null, null);
// moveToFirst()方法将数据的指针移动到第一行的位置,然后进入了一个循环当中,去遍历查询到每一行的数据
if (cursor.moveToFirst()) {
do {
// 遍历Cursor对象,取出数据并打印
// Cursor的getColumnIndex()方法获取到某一列在表中对应的位置索引,然后将这个索引传入到相应的取值方法中,就可以得到数据库中的读取到的数据了
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(TAG, "name = " + name + " " + "author = " + author + " " + "pages = " + pages + " "+ "price = " + price );
} while (cursor.moveToNext());
}
// 注意:最后一定调用close()方法
cursor.close();
- query()方法中7个参数的含义:

(二)使用LitePal
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式。
LitePal使用
配置LitePal
-
添加依赖
compile 'org.litepal.android:core:1.3.2' -
在app/src/main下创建一个名为assets的Directory,在assets目录下创建一个litepal.xml文件
<?xml version="1.0" encoding="utf-8"?>
<litepal>
<!--<dbname>标签用于指定数据库名-->
<dbname value="BookStore"></dbname>
<!--<version>标签用于指定数据版本号-->
<version value="1"></version>
<!--<list>标签用于指定所有的映射类型-->
<list>
<mapping class="com.wzg.litepaltest.Book"></mapping>
<mapping class="com.wzg.litepaltest.Category"></mapping>
</list>
</litepal>
Book类,主要要继承
DataSupport
public class Book extends DataSupport{
private int id;
private String author;
private double price;
private int pages;
private String name;
private String press;
public String getPress() {
return press;
}
public void setPress(String press) {
this.press = press;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
MainActivity
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button createDatabase = findViewById(R.id.create_database);
createDatabase.setOnClickListener(this);
Button addData = findViewById(R.id.add_data);
addData.setOnClickListener(this);
Button updateData = findViewById(R.id.update_data);
updateData.setOnClickListener(this);
Button deleteData = findViewById(R.id.delete_data);
deleteData.setOnClickListener(this);
Button queryData = findViewById(R.id.query_data);
queryData.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.create_database:
// 创建数据库
Connector.getDatabase();
break;
// 添加数据
case R.id.add_data:
Book book = new Book();
book.setName("The Da Vinci Code");
book.setAuthor("Dan Brown");
book.setPages(454);
book.setPrice(16.96);
book.save();
break;
// 更新数据
case R.id.update_data:
// 第一种更新数据的方式
Book book1 = new Book();
book1.setName("The Lost Symbol");
book1.setAuthor("Dan Brown");
book1.setPages(510);
book1.setPrice(19.96);
book1.setPress("Unknow");
book1.save();
book1.setPrice(10.99);
book1.save();
// 第二种方式更新数据的方式
Book book2 = new Book();
book2.setPrice(14.96);
book2.setPress("Anchor");
// 使用updateAll()指定一个约束。
book2.updateAll("name= ? and author = ?", "The Lost Symbol", "Dan Brown");
// 对于所有想要将为数据更新成默认值的操作,LitePal提供了统一setToDefault()方法,然后传入相应的列名就可以了
Book book3 = new Book();
book3.setToDefault("pages");
// updateAll()方法中没有指定约束条件,更新操作对所有数据都生效了
book3.updateAll();
break;
// 删除数据
case R.id.delete_data:
// 第一种删除方式: 调用已存储对象的delete()方法
// 第二种方式
DataSupport.deleteAll(Book.class, "price < ?", "15");
break;
// 查询数据
case R.id.query_data:
List<Book> books = DataSupport.findAll(Book.class);
for (Book book5 : books) {
Log.d(TAG, "name = " + book5.getName() + " author = " + book5.getAuthor() + "pages = " + book5.getPages() + "price = " + book5.getPrice() + "press = " + book5.getPress());
}
break;
}
}
}

