Android学习笔记-SQLite和Content Provider

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);
导出数据库文件:


访问成功.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值