SQLite数据库
SQLite是用C语言写的开源嵌入式数据库引擎,是一款轻型的数据库。设计目标为嵌入式的,占用资源低,处理速度快,能结合C#、PHP、Java等语言,以及ODBC接口。
特点
零配置,数据库支持2TB大小,源代码大约3万行,250k,开源。
数据类型
SQLite采用的是动态数据类型,会根据存入值自动判断。具有以下五种数据类型:
1.NULL:空值
2.INTEGER:带符号的整型,具体取决存入数字的范围大小
3.REAL:浮点数字,存储为8-byte IEEE浮点数
4.TEXT:字符串文本
5.BLOB:二进制对象
SQLite也能接受varchar(n),char(n),decimal(p,s) 等数据类型,只不过使用时会自动转换成上面的五种数据类型。
SQLite可以保存任何类型的数据到任何字段中,无论这列声明的数据类型,(主键定义为INTEGER除外)。
不支持:外键约束、RIGHT OUTER JOIN、FULL OUTER JOIN、ALTER TABLE
数据库版本管理SQLiteOpenHelper
SQLiteOpenHelper是一个抽象类,必须继承它才能使用。
package com.edu.util;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class DBUtil extends SQLiteOpenHelper {
public DBUtil(Context context) {
/**
* 1.数据创建位置
* 2.数据库文件名
* 3.游标,null 默认方式
* 4.版本号
*/
super(context, "edu.db", null, 1);
}
/**
* 获取SQLiteDateBase对象的时候,自动执行
* @param db
*/
@Override
public void onCreate(SQLiteDatabase db) {
//建表
String sql = "create table stu_info"
+ "("
+ "stu_id integer PRIMARY KEY"
+ "stu_name text,"
+ "stu_age text"
+ ")";
db.execSQL(sql);
System.out.println("END");
}
/**
* 版本号变更,自动执行
* 先删除,然后创建
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
//删除表
String sql = "drop table if exists stu_info";
db.execSQL(sql);
onCreate(db);
}
}
CRUD操作SQLiteDatabase
SQLiteDatabase可以通过SQLiteOpenHelper的子类获得实例
getWriteableDatabase():以读写方式打开数据库,磁盘满了,会报异常
getReadableDatabase():先执行getWriteableDatabase,失败的情况下才调用
SQL语句
insert delete update
DBUtil util = new DBUtil(this, rp);
SQLiteDatabase db = util.getWritableDatabase();
<span style="white-space:pre"> </span>//Object[] params = {};
String sql1 = "insert into user_info(user_id,user_name) "
+ "values(1,'张三')";
String sql2 = "delete from user_info where user_id = ? ";
String sql3 = "update user_info set user_name=?,password=?,sex=?"
+ " where user_id = ? ";
db.execSQL(sql);
//db.execSQL(sql2, params);
//db.execSQL(sql3, params);
select
<span style="white-space:pre"> </span>List<HashMap<Object, Object>> list = new ArrayList<>();
HashMap<Object, Object> hashMap = null;
try {
db = dbUtil.getReadableDatabase();
Cursor cursor = db.rawQuery(sql, (String[]) objects);
String[] names = cursor.getColumnNames();
while(cursor.moveToNext()){
hashMap = new HashMap<>();
for(String str : names){
hashMap.put(str, cursor.getString(cursor.getColumnIndex(str)));
}
list.add(hashMap);
}
//关闭游标
cursor.close();
} catch (Exception e) {
throw new RuntimeException("exception:BaseDao.executeQuery()", e);
} finally{
if(db != null && db.isOpen()){
db.close();
}
}
表名操作
<span style="white-space:pre"> </span>db.insert(table, nullColumnHack, values);
db.delete(table, whereClause, whereArgs);
db.update(table, values, whereClause, whereArgs);
db.query(table, columns, selection, selectionArgs, groupBy, having, orderBy);
*注:values为键值对形式
ContentValues cv = new ContentValues();
cv.put("username", "zhangsan");
Demo:
为了方便操作数据库,在assets文件夹下创建db.properties文件(*注:"\"为换行符,即"\\n")
database_name=work.db
version=1
table_create=create table user_info\
(\
user_id integer PRIMARY KEY,\
user_name text,\
password text,\
sex text\
)
创建一个工具类,继承SQLiteOpenHelper抽象类,重写OnCreate和OnUpgrade方法,获取资源文件中的SQL建表语句。
package com.edu.util;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* 数据库操作帮助类
* @author xukai
* 2015年11月28日
*
*/
public class DBUtil extends SQLiteOpenHelper {
private ReadProperties rp;
/**
* @param context 上下文
* @param rp properties文件
*/
public DBUtil(Context context, ReadProperties rp) {
super(context, rp.getDataBaseName(), null, rp.getDataBaseVersion());
this.rp = rp;
}
/**
* <p>创建表语句,SQLiteDatabase.getReadableDatabase() or
* getWriteableDatabase时执行</p>
*/
@Override
public void onCreate(SQLiteDatabase db) {
String[] array = rp.getCreateSQL();
for(String str : array){
db.execSQL(str);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion,
int newVersion) {
}
}
数据访问对象BaseDAO:
package com.edu.dao;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import com.edu.util.DBUtil;
import com.edu.util.ReadProperties;
public class BaseDao {
private DBUtil dbUtil;
private ReadProperties rp;
private SQLiteDatabase db;
public BaseDao(Context context) {
rp = new ReadProperties(context);
dbUtil = new DBUtil(context, rp);
}
/**
* 执行insert delete update操作
* @param sql SQL语句
* @param objects 值
*/
protected void executeUpdate(String sql, Object...objects){
try {
db = dbUtil.getWritableDatabase();
/**
* 判断参数是否为空
*/
if(objects != null && objects.length > 0){
db.execSQL(sql, objects);
}else{
db.execSQL(sql);
}
} catch (SQLException e) {
throw new RuntimeException("exception:BaseDao.executeUpdate()", e);
} finally{
if(db != null && db.isOpen()){
db.close();
}
}
}
/**
* 执行查询操作
* @param sql SQL语句
* @param objects 条件
* @return List<HashMap<Object, Object>> 结果集
*/
protected List<HashMap<Object, Object>> executeQuery(String sql, Object[] objects){
List<HashMap<Object, Object>> list = new ArrayList<>();
HashMap<Object, Object> hashMap = null;
try {
db = dbUtil.getReadableDatabase();
Cursor cursor = db.rawQuery(sql, (String[]) objects);
String[] names = cursor.getColumnNames();
while(cursor.moveToNext()){
hashMap = new HashMap<>();
for(String str : names){
hashMap.put(str, cursor.getString(cursor.getColumnIndex(str)));
}
list.add(hashMap);
}
//关闭游标
cursor.close();
} catch (Exception e) {
throw new RuntimeException("exception:BaseDao.executeQuery()", e);
} finally{
if(db != null && db.isOpen()){
db.close();
}
}
return list;
}
}
UserInfo数据库操作实现类:UserInfoDAOImpl
package com.edu.dao.impl;
import java.util.HashMap;
import java.util.List;
import android.content.Context;
import com.edu.dao.BaseDao;
/**
* 数据库操作实现类
* @author xukai
* 2015年11月28日
*
*/
public class UserInfoDaoImpl extends BaseDao {
public UserInfoDaoImpl(Context context) {
super(context);
}
/**
* 添加
*/
public void save(Object[] objects){
String sql = "insert into user_info(user_name, password, sex)"
+ " values(?, ?, ?)";
super.executeUpdate(sql, objects);
}
/**
* 删除
*/
public void delete(Object[] objects){
String sql = "delete from user_info where user_id = ? ";
super.executeUpdate(sql, objects);
}
/**
* 更改
*/
public void update(Object[] objects){
String sql = "update user_info set user_name=?,password=?,sex=?"
+ " where user_id = ? ";
super.executeUpdate(sql, objects);
}
/**
* 查询所有
*/
public List<HashMap<Object, Object>> find(){
String sql = "select * from user_info ";
return super.executeQuery(sql, null);
}
}
对上面Android Project项目进行测试:
1.在要测试的项目的AndroidManifest.xml中
<instrumentation android:targetPackage="com.edu.pro1125_sqlite_work" android:name="android.test.InstrumentationTestRunner"></instrumentation>
<application
<span style="white-space:pre"> </span><!-- 添加 -->
<uses-library android:name="android.test.runner"/>
</application>
2.创建一个测试工程 new Android Test Project
3.创建JUnit Test Case,选择JUnit4,继承android.test.AndroidTestCase
package com.edu.pro1125_sqlite_work.test;
import org.junit.Before;
import org.junit.Test;
import android.test.AndroidTestCase;
import com.edu.dao.impl.UserInfoDaoImpl;
public class TestUserInfoImpl extends AndroidTestCase {
private UserInfoDaoImpl dao;
@Before
protected void setUp() throws Exception {
super.setUp();
dao = new UserInfoDaoImpl(getContext());
}
@Test
public void test() {
dao.save(new Object[]{"测试用户1","111","男"});//其他方法测试相同
}
}
右键,run as->JUnit Test Case,测试通过,在模拟器File Explorer中data/data/package_name/databases/database_name.db,导出该文件,可以通过Navicat查看数据。
SQLite事务
//开启事务
db.beginTransaction();
执行dml更新操作
db.setTransactionSuccessful(); //设置事务成功完成
db.endTransaction();//结束事物
//当程序执行到此方法时,会检查事务的标志是否成功,如果成功则提交事务,否则回滚事务,
在执行此方法前必须调用db.setTransactionSuccessful(),否则回滚事务
Content Provider
ContentProvider是所有应用程序之间数据存储和检索的桥梁,它的作用是使各个应用程序之间实现数据共享.如:微信读取联系人手机号码。
当应用继承ContentProvider类,并重写该类用于提供数据和存储数据的方法,就可以向其他应用共享其数据。ContendProvider是以类似数据库中表的方式将数据暴露,外界获取数据通过Uri访问ContentProvider。
每个ContentProvider都会对外提供一个公共的Uri,由三部分组成:“content://”+数据的路径+标识ID
Project1:创建user_info,和book_info表
自定义ContentProvider:
package com.edu.contentprovider;
import com.edu.util.DBUtil;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class MyContentProvider extends ContentProvider {
private DBUtil dbutil;
private SQLiteDatabase db;
//常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码
private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
/**
* 添加Uri,如果匹配,返回匹配码
*/
static{
matcher.addURI("com.edu.contentprovider", "user_info", 1);
matcher.addURI("com.edu.contentprovider", "book_info", 2);
}
@Override
public boolean onCreate() {
dbutil = new DBUtil(getContext());
return false;
}
/**
*
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
String table = "";
//匹配Uri,返回对应码
switch (matcher.match(uri)) {
case 1:
table = "user_info";
break;
case 2:
table = "book_info";
}
db = dbutil.getReadableDatabase();
return db.query(table, projection, selection, selectionArgs, null, null, sortOrder);
}
//返回数据的格式
@Override
public String getType(Uri uri) {
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
String table = "";//根据对应Uri,判断操作的表
switch (matcher.match(uri)) {
case 1:
table = "user_info";
break;
case 2:
table = "book_info";
}
db = dbutil.getWritableDatabase();
db.insert(table, null, values);
return null;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
db = dbutil.getWritableDatabase();
return db.delete("user_info", selection, selectionArgs);
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
db = dbutil.getWritableDatabase();
return db.update("user_info", values, selection, selectionArgs);
}
}
AndroidManifest.xml:
application节点下:
<span style="white-space:pre"> </span><provider
android:name="com.edu.contentprovider.MyContentProvider"
android:authorities="com.edu.contentprovider"
android:exported="true"></provider>
Project2:
对Project1中的表进行操作
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
// values.put("user_name", "马莎莎");
// values.put("user_pwd", "123456");
values.put("book_name", "Java程序设计");
values.put("book_price", "80.0");
values.put("book_num", "10");
//格式 contend://provider_name -> android:authorities
Uri uri = Uri.parse("content://com.edu.contentprovider/book_info");
cr.insert(uri, values);
导出数据库文件:
访问成功.