涉及到数据库的操作一般的都是使用第三方的框架,如GreeoDao,OrmLitem等。或者是直接利用SQLiteOpenHelper来完成数据库的增删改查以及数据库升级。那么对于这种写法,一般都比较繁琐。操作如下:
DBHelper dbHelper = new DBHelper(this);
SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
sqLiteDatabase.execSQL("create table if not exists tb_weichat(name varchar(20),password varchar(10))");
ContentValues contentValues = new ContentValues();
contentValues.put("user_name","张三");
contentValues.put("password","123456");
sqLiteDatabase.beginTransaction();
int scheduleID = -1;
dbHelper.insert("schedule",null,values);
dbHelper.setTransctionSuccessful();
使用框架实现
User user = new User("张三", "20122425");
baseDao.insert(user);
`可以看出使用框架和之前相比省了很多行代码。操作更简单。
用到的知识点
泛型
注解
反射
数据库语句拼接
用到的设计的模式
单例模式
简单工厂模式
模板方法模式
3类图
4 具体实现
IBaseDao
public interface IBaseDao {
/**
* 数据库插入操作
* @param entity
* @return
*/
Long insert(T entity);
/**
* 数据库删除
* @param where
* @return
*/
int delete(T where);
/**
* 数据库更改操作
* @param entity
* @param where
* @return
*/
int updata(T entity,T where);
/**
* 数据库查询操作
* @param where
* @return
*/
List query(T where);
}
这个借口约束了数据库行为,数据库中有增删改查功能。
BaseDao
public abstract class BaseDao implements IBaseDao {
//只能初始化一次
private boolean isInit = false;
//被插入数据库的实体
private Class mEntityClass;
private SQLiteDatabase mSqLiteDatabase;
//表名
private String tableName;
/**
* 用来维护表与实体的对应关系
* key: 表的列名
* value: entity的Field名
*/
private HashMap cacheMap;
/**
* @param entityClass 要出入数据库的实体类
* @param sqLiteDatabase 数据库管理的对象
*/
public synchronized boolean init(Class entityClass, SQLiteDatabase sqLiteDatabase) {
if (!isInit) {
mEntityClass = entityClass;
mSqLiteDatabase = sqLiteDatabase;
if (mEntityClass.getAnnotation(DbTable.class) != null) {
//注解DbTable的值为表名
tableName = entityClass.getAnnotation(DbTable.class).value();
} else {
//如果没有注解,对应的类名为表名
tableName = entityClass.getSimpleName();
}
//创建表
if (!TextUtils.isEmpty(createTable())) {
sqLiteDatabase.execSQL(createTable());
}
cacheMap = new HashMap<>();
initCacheMap();
isInit = true;
}
return isInit;
}
/**
* 初始化cacheMap,
* 将表的列明和对应的entity的成员变量名字赋值给该cacheMap
*/
private void initCacheMap() {
String sql = "select * from " + this.tableName + " limit 1,0";
Cursor cursor = null;
try {
cursor = mSqLiteDatabase.rawQuery(sql, null);
//表的列名数组
String[] columnsName = cursor.getColumnNames();
//entitiy的Field数组
Field[] fields = mEntityClass.getFields();
//防止私有属性无法访问
for (Field field : fields) {
field.setAccessible(true);
}
//遍历列名
for (String columnName : columnsName) {
//遍历成员变量
for (Field field : fields) {
String fieldName = null;
if (field.getAnnotation(DbField.class) != null) {
fieldName = field.getAnnotation(DbField.class).value();
} else {
fieldName = field.getName();
}
if (field != null && columnName.equals(fieldName)) {
cacheMap.put(columnName, field);
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != cursor) {
cursor.close();
}
}
}
//=============================================插入
@Override
public Long insert(T entity) {
Map map = getValue(entity);
ContentValues contentValues = getContentValues(map);
Long reslt = mSqLiteDatabase.insert(tableName, null, contentValues);
return reslt;
}
//=============================================删除
@Override
public int delete(T where) {
int result = -1;
Map whereClause = getValue(where);
Condition condition = new Condition(whereClause);
result = mSqLiteDatabase.delete(tableName, condition.getWhereClause(), condition.getWhereArgs());
return result;
}
//=============================================更新
@Override
public int updata(T entity, T where) {
int result = -1;
Map whereClause = getValue(where);
Map values = getValue(entity);
Condition condition = new Condition(whereClause);
ContentValues contentValues = getContentValues(values);
result = mSqLiteDatabase.update(tableName, contentValues, condition.getWhereClause(), condition.getWhereArgs());
return result;
}
//=============================================更新
@Override
public List query(T where) {
return query(where, null, null, null);
}
private List query(T where, String orderBy, Integer startIndex, Integer limit) {
Map map = getValue(where);
String limitString = null;
if (startIndex != null && limit != null) {
limitString = startIndex + " , " + limit;
}
Condition condition = new Condition(map);
Cursor cursor = mSqLiteDatabase.query(tableName, null, condition.getWhereClause(), condition.getWhereArgs(), null, null, orderBy, limitString);
List result = getResult(where, cursor);
cursor.close();
return result;
}
/**
* 将查询的结果返回
* @param where 表中每条数据对应的实体类
* @param cursor 查询结果返回的cursor对象
* @return 返回所有的查询结果
*/
protected List getResult(T where, Cursor cursor) {
ArrayList list = new ArrayList();
Object item;
//先遍历表中的所有行
while (cursor.moveToNext()) {
try {
//根据一行 创建一个实例
item = where.getClass().newInstance();
Iterator iterator = cacheMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
//得到列名
String columnName = (String) entry.getKey();
//根据列名 得出列的位置
Integer columnIndex = cursor.getColumnIndex(columnName);
Field field = (Field) entry.getValue();
//获取Field的类型
Class type = field.getType();
//判断Field的类型
if (columnIndex != -1) {
if (type == String.class) {
//根据反射进行赋值
field.set(item, cursor.getString(columnIndex));
} else if (type == Double.class) {
field.set(item, cursor.getDouble(columnIndex));
} else if (type == Integer.class) {
field.set(item, cursor.getInt(columnIndex));
} else if (type == Long.class) {
field.set(item, cursor.getLong(columnIndex));
} else if (type == Byte.class) {
field.set(item, cursor.getBlob(columnIndex));
//不支持类型
} else {
continue;
}
}
}
list.add(item);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return list;
}
;
/**
* 把map转成contentValues
* key:列名 value:Field值
*
* @param map
* @return
*/
private ContentValues getContentValues(Map map) {
ContentValues contentValues = new ContentValues();
Set keys = map.keySet();
Iterator iterator = keys.iterator();
while (iterator.hasNext()) {
String columnName = iterator.next();
String value = map.get(columnName);
if (!TextUtils.isEmpty(columnName) && !TextUtils.isEmpty(value)) {
contentValues.put(columnName, value);
}
}
return contentValues;
}
;
/**
* 用map 来存储entity的属性值 key为对应属性的注解值
* key:"user_name" vlaue:"张三"
*
* @param entity
* @return
*/
private Map getValue(T entity) {
Map map = new HashMap<>();
Iterator fieldIterator = cacheMap.values().iterator();
while (fieldIterator.hasNext()) {
Field field = fieldIterator.next();
String key = null; //列名
String value = null; //field值
if (field.getAnnotation(DbField.class) != null) {
key = field.getAnnotation(DbField.class).value();
} else {
key = field.getName();
}
try {
if (field.get(entity) == null) {
continue;
}
value = field.get(entity).toString();
if (value != null) {
map.put(key, value);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
class Condition {
/**
* 条件语句
* name=?&&password=?
*/
private String whereClause;
private String[] whereArgs;
public Condition(Map whereClause) {
ArrayList list = new ArrayList();
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(" 1=1 ");
Set keySet = whereClause.keySet();
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
String key = iterator.next();
String value = whereClause.get(key);
if (key != null) {
//拼接条件语句 1=1 and name =? and password =?
stringBuilder.append(" and " + key + " =?");
list.add(value);
}
}
this.whereClause = stringBuilder.toString();
this.whereArgs = (String[]) list.toArray(new String[list.size()]);
}
public String getWhereClause() {
return whereClause;
}
public String[] getWhereArgs() {
return whereArgs;
}
}
/**
* 每个Dao的建的表各不相同,所以此方法留给子类实现
*
* @return 建表的字符串语句
*/
public abstract String createTable();
}
这个方法做了这几件事情:
初始化每一条数据对应的实体类。
mEntityClass = entityClass;
初始化SQLiteDataBase对象
mSqLiteDatabase = sqLiteDatabase;
初始化表名
if (mEntityClass.getAnnotation(DbTable.class) != null) {
//注解DbTable的值为表名
tableName = entityClass.getAnnotation(DbTable.class).value();
} else {
//如果没有注解,对应的类名为表名
tableName = entityClass.getSimpleName();
}
创建表 这里的createTalbe方法是抽象方法,也是BaseDao子类唯一需要重写的方法。也就是说BaseDao的子类除了建表语句不同之外,其他的方法都是一样的。
if (!TextUtils.isEmpty(createTable())) {
sqLiteDatabase.execSQL(createTable());
}
初始化cacheMap
cacheMap = new HashMap<>();
initCacheMap();