Android之数据库
首先来简单介绍下Android的数据库。
SQLite
SQLite,是一个支持SQL的轻量级的嵌入式数据库。
SQLiteDatabase:Android数据库中使用最多的一个类,通过它可以实现数据库的创建、打开,new一个新表,实现增删改查。每次用完之后要记得将数据库close掉。
SQLiteOpenHelper:是一个抽象类,通常定义一个类来继承它,实现onCreate,onUpdate方法。
SQLite数据类型
一般数据采用的固定的静态数据类型,而SQLite采用的是动态数据类型,会根据存入值自动判断。SQLite具有以下几种常用的数据类型:
NULL: 这个值为空值
VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。
CHAR(n):长度固定为n的字串,n不能超过 254。
INTEGER: 值被标识为整数,依据值的大小可以依次被存储为1,2,3,4,5,6,7,8.
REAL: 所有值都是浮动的数值,被存储为8字节的IEEE浮动标记序号.
TEXT: 值为文本字符串,使用数据库编码存储(TUTF-8, UTF-16BE or UTF-16-LE).
BLOB: 值是BLOB数据块,以输入的数据格式进行存储。如何输入就如何存储,不改 变格式。
DATA :包含了 年份、月份、日期。TIME: 包含了 小时、分钟、秒。
SQLiteDatabase的常用方法
打开或创建数据库
openOrCreateDatabase(String path,SQLiteDatabase.CursorFactory factory)
添加一条记录
insert(String table,String nullColumnHack,ContentValues values)
删除一条记录
delete(String table,String whereClause,String[] whereArgs)
查询一条记录
query(String table,String[] columns,String selection,String[] selectionArgs,String groupBy,String having,String orderBy)
修改记录
update(String table,ContentValues values,String whereClause,String[] whereArgs)
好了现在直接上代码:
数据库主体
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* 数据库Helper类,必须继承自 SQLiteOpenHelper 当一个继承自 SQLiteOpenHelper 后需要复写两个方法,分别是
* onCreate()是在数据库创建的时候调用的,主要用来初始化数据表结构和插入数据初始化的记录
* onUpgrade():onUpGrade是在数据库版本升级的时候调用的,主要用来改变表结构
*/
public class MyDatabaseHelper extends SQLiteOpenHelper {
public MyDatabaseHelper(Context context) {
/**
* 参数说明: 第一个参数: 上下文 第二个参数:数据库的名称 第三个参数:null代表的是默认的游标工厂 第四个参数:是数据库的版本号
* 数据库只能升级,不能降级,版本号只能变大不能变小
*/
super(context, "testdata.db", null, 2);
}
/**
* 如果数据库已经创建过了,则不会执行到该方法。如果不存在的数据库则会执行主要用来初始化数据表结构和插入数据初始化的记录
* 当数据库第一次被创建的时候调用的方法,适合在这个方法里面把数据库的表结构定义出来. 所以只有程序第一次运行的时候才会执行
* 如果想再看到这个函数执行,必须写在程序然后重新安装这个app
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table contactinfo (id integer primary key autoincrement, name varchar(20), author varchar(20),pages varchar(20),price varchar(20))");
}
/**
* 数据库创建时不会执行只有当数据库更新的时候调用的方法 这个要显示出来得在上面的super语句里面版本号发生改变时才会 打印
* (super(context, "itheima.db", null, 2); )
* 注意,数据库的版本号(newVersion)只可以变大,不能变小,假设我们当前写的版本号是3,运行,然后又改成1,运行则报错。不能变小
* VARCHAR(n):长度不固定且其最大长度为 n 的字串,n不能超过 4000。
* @param db
* @param oldVersion
* @param newVersion
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// db.execSQL("alter table contactinfo add account varchar(20)");
for (int i = oldVersion; i < newVersion; i++) {
switch ( i) {
// case value:
//
// break;
default:
break;
}
}
}
}
DatabaseHelper工具类
package com.bd.datatest;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
/**
* 我们这里的每一个 增删改查 的方法都通过getWritableDatabase()去实例化了一个数据库,这里必须这么做 不客气抽取 成为一个成员变量,
* 否则报错,若是觉得麻烦可以通过定义方法来置为null和重新赋值
* —— 其实Tools类在这里做得事情特别简单: 1、定义一个构造方法,利用这个方法去实例化一个 数据库帮助类 2、编写Tools类的对应的 增删改查 方法。
*
*/
public class DatabaseHelperTools {
private MyDatabaseHelper mMyDBHelper;
/**
*实例化数据库Help类,只有得到帮助类的对象我们才可以实例化 SQLiteDatabase
*/
public DatabaseHelperTools(Context context) {
mMyDBHelper = new MyDatabaseHelper(context);
}
public long addDate(String name, String author,String pages,String price) {
// 增删改查每一个方法都要得到数据库,然后操作完成后一定要关闭
// getWritableDatabase(); 执行后数据库文件才会生成
// 数据库文件利用DDMS可以查看,在 data/data/包名/databases 目录下即可查看
SQLiteDatabase sqLiteDatabase = mMyDBHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", name);
contentValues.put("author", author);
contentValues.put("pages", pages);
contentValues.put("price", price);
// 返回,显示数据添加在第几行
// 加了现在连续添加了3行数据,突然删掉第三行,然后再添加一条数据返回的是4不是3
// 因为自增长
long rowid = sqLiteDatabase.insert("contactinfo", null, contentValues);
sqLiteDatabase.close();
return rowid;
}
// 删除的方法,返回值是int
public int deleteDate(String name) {
SQLiteDatabase sqLiteDatabase = mMyDBHelper.getWritableDatabase();
int deleteResult = sqLiteDatabase.delete("contactinfo", "name=?", new String[] { name });
sqLiteDatabase.close();
return deleteResult;
}
/**
* 修改的方法
*
* @param name
* @param newPhone
* @return
*/
public int updateData(String newName, String newAuthor,String newPages,String newPrice) {
SQLiteDatabase sqLiteDatabase = mMyDBHelper.getWritableDatabase();
ContentValues contentValues = new ContentValues();
contentValues.put("name", newName);
contentValues.put("author", newAuthor);
contentValues.put("pages", newPages);
contentValues.put("price", newPrice);
int updateResult = sqLiteDatabase.update("contactinfo", contentValues, "name=?", new String[] { newName });
sqLiteDatabase.close();
return updateResult;
}
/**
* 查询的方法(价格)
*
* @param name
* @return
*/
public String alterDate(String name) {
String price = null;
SQLiteDatabase readableDatabase = mMyDBHelper.getReadableDatabase();
// 查询比较特别,涉及到 cursor
Cursor cursor = readableDatabase.query("contactinfo", new String[] { "price" }, "name=?", new String[] { name },
null, null, null);
if (cursor.moveToNext()) {
price = cursor.getString(0);
}
cursor.close(); // 记得关闭 corsor
readableDatabase.close(); // 关闭数据库
return price;
}
}
测试界面
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
private static final String TAG = "Datatest";
private EditText metName, metAuthor, metPages, metPrice;
private Button mBt_add,mBt_delete,mBt_update,mBt_query;
private DatabaseHelperTools mDataTools;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
}
private void initView() {
metName = (EditText) findViewById(R.id.et_name);
metAuthor = (EditText) findViewById(R.id.et_author);
metPages = (EditText) findViewById(R.id.et_pages);
metPrice = (EditText) findViewById(R.id.et_price);
mBt_add = (Button) findViewById(R.id.bt_add);
mBt_add.setOnClickListener(this);
mBt_delete = (Button) findViewById(R.id.bt_delete);
mBt_delete.setOnClickListener(this);
mBt_update = (Button) findViewById(R.id.bt_update);
mBt_update.setOnClickListener(this);;
mBt_query = (Button) findViewById(R.id.bt_query);
mBt_query.setOnClickListener(this);
}
private void initData() {
mDataTools = new DatabaseHelperTools(MainActivity.this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.bt_add:
addData();
break;
case R.id.bt_delete:
deleteData();
break;
case R.id.bt_update:
upDateData();
break;
case R.id.bt_query:
queryData();
break;
default:
break;
}
}
private void addData() {
Log.e(TAG, "addData()");
String name = metName.getText().toString().trim();
String author = metAuthor.getText().toString().trim();
String pages = metPages.getText().toString().trim();
String price = metPrice.getText().toString().trim();
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(author) || TextUtils.isEmpty(pages)
|| TextUtils.isEmpty(price)) {
Toast.makeText(this, "请完善数据", Toast.LENGTH_SHORT).show();
return;
} else {
long addLong = mDataTools.addDate(name, author, pages, price);
if (addLong == -1) {
Toast.makeText(this, "添加失败", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "数据添加在第 " + addLong + " 行", Toast.LENGTH_SHORT).show();
}
}
}
private void deleteData() {
Log.e(TAG, "deleteData()");
String name = metName.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(this, "请完善数据", Toast.LENGTH_SHORT).show();
return;
} else {
int deleteDate = mDataTools.deleteDate(name);
if (deleteDate == -1) {
Toast.makeText(this, "删除失败", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "成功删除 " + deleteDate + " 条数据", Toast.LENGTH_SHORT).show();
}
}
}
private void upDateData() {
Log.e(TAG, "upDateData()");
String name = metName.getText().toString().trim();
String author = metAuthor.getText().toString().trim();
String pages = metPages.getText().toString().trim();
String price = metPrice.getText().toString().trim();
if (TextUtils.isEmpty(name) || TextUtils.isEmpty(author) || TextUtils.isEmpty(pages)
|| TextUtils.isEmpty(price)) {
Toast.makeText(this, "请完善数据", Toast.LENGTH_SHORT).show();
return;
} else {
int count = mDataTools.updateData(name, author, pages, price);
if (count == -1) {
Toast.makeText(this, "更新失败", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "数据更新了 " + count + " 行", Toast.LENGTH_SHORT).show();
}
}
}
private void queryData() {
Log.e(TAG, "queryData()");
String name = metName.getText().toString().trim();
if (TextUtils.isEmpty(name)) {
Toast.makeText(this, "请完善数据", Toast.LENGTH_SHORT).show();
return;
} else {
String priceResult = mDataTools.alterDate(name);
Toast.makeText(this, "价格为: " + priceResult, Toast.LENGTH_SHORT).show();
}
}
}
布局文件 activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.bd.datatest.MainActivity" >
<EditText
android:id="@+id/et_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输书名" >
</EditText>
<EditText
android:id="@+id/et_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入作者" />
<EditText
android:id="@+id/et_pages"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入页码" />
<EditText
android:id="@+id/et_price"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入价格" />
<Button
android:id="@+id/bt_add"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="添加" />
<Button
android:id="@+id/bt_delete"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="删除" />
<Button
android:id="@+id/bt_update"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="update"
android:text="修改" />
<Button
android:id="@+id/bt_query"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="查询" />
</LinearLayout>