一.简介
SQLite是一款开源的、嵌入式关系型数据库,第一个版本Alpha发布于2000年。SQLite在便携性、易用性、紧凑性、高效性和可靠性方面有着突出的表现。
SQLite和C/S模式的数据库软件不同,它是一款嵌入式数据库,没有独立运行的进程,与所服务的应用程序在应用程序进程空间内共生共存。它的代码与应用程序代码也是在一起的,或者说嵌入其中,作为托管它的程序的一部分。因此不存在数据库的客户端和服务器,使用SQLite一般只需要带上它的一个动态库,就可以享受它的全部功能。
数据库服务器在程序中的好处是不需要网络配置或管理。将数据库客户端与服务器运行在同一个进程中,可以省去不少的操作及麻烦:不用担心防火墙或者地址解析;不用浪费时间管理复杂的授权和权限;可以减少网络调用相关的消耗;可以简化数据库管理并使程序更容易部署。
SQLite数据库通过数据库级上的独占性和共享锁来实现独立事务处理。这意味着多个进程可以在同一时间从同一数据库读取数据,但是只有一个可以写入数据。在某个进程向数据库执行写操作之前,必须获得独占锁定。在发出独占锁定后,其他的读写操作将不会再发生。
此外,SQLite数据库中的所有信息(比如表、视图、触发器等)都包含在一个文件内,方便管理和维护。SQLite数据库还支持大部分操作系统,除电脑上使用的操作系统之外,很多手机上使用的操作系统同样可以运行。同时,SQLite数据库还提供了多语言的编程接口,供开发者使用。
二.SQLite的相关类
- SQLiteOpenHelper:抽象类,通过继承该类,重写数据库创建以及更新的方法, 我们还可以通过该类的对象获得数据库实例,或者关闭数据库
- SQLiteDatabase:数据库访问类:通过该类的对象来对数据库做一些增删改查的操作
- Cursor:游标,类似于JDBC里的resultset(结果集),可以简单理解为指向数据库中某一个记录的指针
三.优化格式
1.正常的数据库创建流程
首先基本上在进行android的SQLite的时候,基本上每次进行表格修改的时候都会进行一次数据库table的创建。
一般都是继承SQLiteOpenHelper 来实现数据库的表的创建,但是如果数据库的表每次都需要修改的话,每次都进行修改是否太麻烦了,而且如果你的项目中的依赖module太多,或者这个他是在maven当中,再找到他是不是很麻烦。
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
/**
* Created by 先森 on 2017/9/21.
*/
public static final String CREATE_BOOK = "CREATE TABLE book ("
+ "id integer PRIMARY KEY Autoincrement ,"
+ "author text ,"
+ "price real ,"
+ "pages integer,"
+ "name text )";
/**
* integer:整形
* real:浮点型
* text:文本类型
* blob:二进制类型
* PRIMARY KEY将id列设置为主键
* AutoIncrement关键字表示id列是自动增长的
*/
public class DatabaseHelper extends SQLiteOpenHelper {
public DatabaseHelper(Context context, String name, int version) {
super(context, name, null, version);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
sqLiteDatabase.execSQL(CREATE_BOOK);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
2.配置一个ddl.sql数据库表和关键字的文件
所以我觉得不如就把他这个数据库表创建的sql语句放在一个资源文件当中相当于是一个配置文件了,这样配置字段什么的不仅看起来十分方便,而且十分方便去修改它。其次我们只要进行文件的读取,再转换成String格式不就可以了么
下面把数据库创建的表sql语句如下,创建一个table1,版本号version :1
# ddl版本号
version=1
# 存储配置表
# 如果存在则删除表
drop table if exists table1;
create table table1(
id varchar(200) not null, # 存储的key
json text, # 存储的内容
primary key(id)
)
3.对文件ddl读取
1.读取输入流把它变成String格式的文件
2.获取版本号
3.通过split来把Stringbuilder格式SQL语句变成String[]格式
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* Created by 张都 on 2017/9/20.
*/
public class DDLReader {
private BufferedReader bufferedReader;
private StringBuilder allsql;
private int version;
public DDLReader(InputStream in) {
this.bufferedReader = new BufferedReader(new InputStreamReader(in));
allsql=new StringBuilder();
version=0;
}
public void read(){
try {
while(bufferedReader.ready()){
String line=bufferedReader.readLine();
if(line==null){
break;
}
lineRead(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
//数据库的每条读取
private void lineRead(String line) {
if(line.isEmpty())return;
line=line.replaceAll("\\/\\*[\\S\\s]*?\\*\\/","").replaceAll("\\/\\/[\\S\\s]*$","").replaceAll("\\#[\\S\\s]*$","").trim();
if(line.isEmpty())return;
if(line.startsWith("version")){
String[] versions=line.split("=");
if(versions.length<2){
throw new RuntimeException("ddl文件version设置错误 必须version=版本号为单独一行");
}
try {
this.version=Integer.valueOf(versions[1].trim());
}catch (Exception e){
throw new RuntimeException("ddl文件version设置错误 version必须为正整数");
}
return;
}
allsql.append(line);
}
//获取当前数据库版本
public int getVersion(){
return version;
}
/**
* 返回所有创建数据库的sql语句
* @return
*/
public String[] getAllddlsSql(){
String[] ddl=allsql.toString().split(";");
return ddl;
}
}
定义一个接口对返回的数据的格式和种类进行
public interface IDao {
/**
* 查询
* @param sql 查询语句
* @return
*/
List> query(String sql);
/**
* 查询返回第几页的个数
* @param sql 查询语句
* @return
*/
List> query(String sql,int page,int pageSize);
/**
* 插入和更新操作
* @param sql 查询语句
* @return
*/
int update(String sql);
/**
*获取本地数据库的数据个数
* @param sql 查询语句
* @return
*/
int getCount(String sql);
}
实现接口进行具体方法的实现
public class Dao implements IDao {
//数据库版本
private int version;
//创建数据库的sql
private String[] ddls;
//获取数据库
private SQLiteDatabase db;
public Dao(Context context,String name) {
getDDLs(context);
this.db=new DataBaseHelper(context, name,version,ddls).getWritableDatabase();
}
private void getDDLs(Context context){
try{
InputStream in=context.getResources().openRawResource(R.raw.ddl);
DDLReader ddlReader=new DDLReader(in);
ddlReader.read();
version=ddlReader.getVersion();
ddls=ddlReader.getAllddlsSql();
}catch (Exception e){
throw new RuntimeException("ddl的version或者ddls没找到或者文件ddl没找到");
}
}
@Override
public List> query(String sql) {
if(db==null){
return null;
}else{
Cursor cursor = db.rawQuery(sql, null);
try {
List> list = new ArrayList();
while (cursor.moveToNext()) {
HashMap map = new HashMap();
for (int i = 0; i < cursor.getColumnCount(); i++) {
Log.i(cursor.getColumnName(i), cursor.getString(i) == null ? "null" : cursor.getString(i));
map.put(cursor.getColumnName(i).toLowerCase(), cursor.getString(i));
}
list.add(map);
}
return list;
}finally {
cursor.close();
}
}
}
@Override
public List> query(String sql, int page, int pageSize) {
int offset=(page-1)*pageSize;
sql="select * from ("+sql+") a limit "+pageSize+" offset "+offset;
return query(sql);
}
@Override
public int update(String sql) {
if(db==null){
return -1;
}else{
try {
db.execSQL(sql);
return 1;
}catch (Exception e){
Log.e("appsql",sql);
e.printStackTrace();
return 0;
}
}
}
@Override
public int getCount(String sql) {
sql="select count(*) from ("+sql+") a";
Cursor cursor = db.rawQuery(sql, null);
try {
cursor.moveToFirst();
return cursor.getInt(0);
}finally {
cursor.close();
}
}
}
最后一步进行相关的输入参数的格式进行规定,提供一个公开的类CacheProvider
转换成json格式的话就需要进行json的依赖
在项目中添加如下fastjso的依赖
compile 'com.alibaba:fastjson:1.1.52.android'
public class CacheProvider {
private static IDao dao;
public static void initDao(Context context, String name){
dao=new Dao(context,name);
}
//插入数据和更新数据
@Nullable
public static void setString(String key,String data){
int size = dao.getCount("select * from storage where id='" + key + "'");
String value=String.valueOf(data).replaceAll("'","\\'");
if (size == 0) {
dao.update("insert into storage values('" + key + "','" + value + "')");
} else {
int s = dao.update("update storage set json='" + value + "' where id='" + key + "'");
}
}
@Nullable
public static void setObject(String key,Object data){
setString(key, JSON.toJSONString(data));
}
@Nullable
public static void setDouble(String key,double v){
setObject(key,v);
}
@Nullable
public static void setObjects(String key,List extends Object> list){
setString(key, JSON.toJSONString(list));
}
@Nullable
public static String getString(String key){
List> list = dao.query("select * from storage where id='" + key + "'");
if (list.isEmpty()) {
return null;
} else {
return list.get(0).get("json").toString();
}
}
/**
* 获取存储的boolean值
* @param key
* @return
*/
@Nullable
public static boolean getBoolean(String key){
return Boolean.valueOf(getString(key));
}
@Nullable
public static int getInteger(String key){
try {
return Integer.valueOf(getString(key));
}catch (Exception e){
return 0;
}
}
@Nullable
public static double getDouble(String key){
try {
return Double.valueOf(getString(key));
}catch (Exception e){
return -1;
}
}
@Nullable
public static T getObject(String key, Class clazz){
String json=getString(key);
if(json==null){
return null;
}
return JSON.parseObject(json,clazz);
}
@NonNull
public static List getObjects(String key, Class clazz){
String json=getString(key);
if(json==null){
return new ArrayList<>();
}
return JSON.parseArray(json,clazz);
}
}