Android数据库设计——2,面向对象(ORM)操作表:增删改查
Posted 夜辉疾风
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android数据库设计——2,面向对象(ORM)操作表:增删改查相关的知识,希望对你有一定的参考价值。
操作表
操作表之前的优化/前置工作
缓存表字段
public class BaseDao<T> implements IBaseDao<T>
//...其他代码
//创建一个缓存,缓存表的字段对应的java实体类成员变量
//key是表的字段
//value是对应的java实体类的成员变量Field对象
private HashMap<String, Field> cacheMap;
//架构内部的逻辑不要提供构造方法给调用层使用,表明靠反射来获得
public void init(SQLiteDatabase sqLiteDatabase, Class<T> entityClass)
//...其他代码
if (!isInit)
//...其他代码
//初始化成员变量缓存
initCacheMap();
isInit = true;
//初始化缓存
private void initCacheMap()
//new一个map集合
if (cacheMap == null)
cacheMap = new HashMap<>();
//取得所有字段名字,通过查询目标表
String sql = "select * from " + tableName + " limit 1,0";//空表
//获得游标
Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
获得表的所有列名
String[] columnNames = cursor.getColumnNames();
//取得所有java对象的公共成员变量
Field[] declaredFields = entityClass.getDeclaredFields();
//打开所有字段的访问权限
for (Field field : declaredFields)
field.setAccessible(true);
//字段和对象成员变量一一对应
//循环数据库中查出来的表中的字段名
for (String columnName : columnNames)
Field columnField = null;
//循环传进来的java实体类的成员变量
for (Field field : declaredFields)
//得到成员变量名
String fieldName;
DbField dbField = field.getAnnotation(DbField.class);
if (dbField != null)
fieldName = dbField.value();
else
fieldName = field.getName();
//表的列名和java对象的成员变量名对应上了,则缓存起来
if (!TextUtils.isEmpty(columnName) && columnName.equals(fieldName))
columnField = field;
break;
//在数据库中匹配到了参数和值,则缓存起来
if (columnField != null)
cacheMap.put(columnName, columnField);
cursor.close();
处理传递进来的数据
将传递进来的对象转化成:表字段—java值的形式
public class BaseDao<T> implements IBaseDao<T>
//...其他代码
//将传递进来的java对象处理成表字段-entity值的map对象
//这里使用缓存去检查传入的属性与表的列是否对应
private Map<String, String> getValues(T entity)
HashMap<String, String> map = new HashMap<>();
//取出缓存中的表字段名和对应的java对象的Field对象
for(Map.Entry<String,Field> entry:cacheMap.entrySet())
//获得缓存的Field对象
Field field = entry.getValue();
//设置可访问变量
field.setAccessible(true);
try
//获取传递进来的entity对象与数据库相对应的属性的值
Object obj = field.get(entity);
//如果没有获取到与表字段对应的属性的值则进入下次循环
if (obj == null) continue;
//获得到了属性对应的值,这里将所有值都当作string处理
String value = obj.toString();
//获取属性名
String key;
if (field.getAnnotation(DbField.class) != null)
key = field.getAnnotation(DbField.class).value();
else
key = field.getName();
//拿到了属性名和属性值
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value))
//加入map
map.put(key, value);
catch (IllegalAccessException e)
e.printStackTrace();
return map;
将需要操作的map对象专程数据库可识别的ContentValues对象
public class BaseDao<T> implements IBaseDao<T>
//...其他代码
//将需要插入的参数和值转换成contentvalues,提供给sqlitedatabase去做添加操作
private ContentValues getContentValues(Map<String, String> map)
ContentValues contentValues = new ContentValues();
if (map == null || map.isEmpty()) return contentValues;
//循环:属性->值
for (Map.Entry<String, String> entry : map.entrySet())
String key = entry.getKey();
String value = entry.getValue();
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value))
//将属性和值一一对应添加进去
contentValues.put(key, value);
return contentValues;
insert
public class BaseDao<T> implements IBaseDao<T>
//……其他代码
@Override
public long insert(T entity)
//准备好要插入的数据
Map<String, String> map = getValues(entity);
//把map中的数据转移到conentvalues中
ContentValues contentValues = getContentValues(map);
//插入
return sqLiteDatabase.insert(tableName, null, contentValues);
update
public class BaseDao<T> implements IBaseDao<T>
//……其他代码
@Override
public long update(T entity, T where)
//修改值
Map<String, String> values = getValues(entity);
ContentValues contentValues = getContentValues(values);
//条件
Map<String, String> values1 = getValues(where);
Condition condition = new Condition(values1);
//执行更新,相当于该代码
//sqLiteDatabase.update(tableName,contentValue,"name = ?",new String[]"test");
return sqLiteDatabase.update(tableName, contentValues, condition.whereClause, condition.whereArgs);
//update的条件语句对象
//要把条件语句转化成数据库认识的对象
private class Condition
private String whereClause;//更新的第一个对象
private String[] whereArgs;//更新的第二个对象
//拿到条件参数
private Condition(Map<String, String> whereMapCasue)
ArrayList<String> list = new ArrayList<>();
StringBuilder stringBuilder = new StringBuilder();
//相当于占位符,让条件语句能够使用and关键字,可以拼接多条条件语句
stringBuilder.append("1 = 1");
for (Map.Entry<String, String> entry : whereMapCasue.entrySet())
String key = entry.getKey();
String value = entry.getValue();
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value))
stringBuilder.append(" and ").append(key).append(" = ?");
list.add(value);
this.whereClause = stringBuilder.toString();
this.whereArgs = list.toArray(new String[list.size()]);
delete
public class BaseDao<T> implements IBaseDao<T>
//……其他代码
@Override
public int delete(T where)
//准备好需要的参数
Map<String, String> values = getValues(where);
Condition condition = new Condition(values);
//执行更新
//sqLiteDatabase.update(tableName,contentValue,"name = ?",new String[]"test");
return sqLiteDatabase.delete(tableName, condition.whereClause, condition.whereArgs);
query
queryByWhere
public class BaseDao<T> implements IBaseDao<T>
//……其他代码
/**
* 条件查询
* @param where 条件
* @param orderBy 排序方式
* @param startIndex 分页,从哪里开始,index
* @param limit 页码,一次查询多少页
* @return 查询结果
*/
@Override
public List<T> queryByWhere(T where, String orderBy, Integer startIndex, Integer limit)
//准备好条件语句
Map<String, String> values = getValues(where);
//分页,从哪里开始(startindex),一次查询多少页(limit)
String limitStr = "";
if (startIndex != null && limit != null)
limitStr = startIndex + " , " + limit;
//传唤条件语句
Condition condition = new Condition(values);
//获得查询游标
Cursor cursor = sqLiteDatabase.query(tableName, null, condition.whereClause, condition.whereArgs, null, null, orderBy, limitStr);
List<T> resultList = getResult(cursor, where);
cursor.close();
return resultList;
//通过游标查询到指定条件的数据
private List<T> getResult(Cursor cursor, T where)
List list = new ArrayList<>();
//游标中是否有结果
while (cursor.moveToNext())
try
//获得传递进来的返回对象的实例
Object item = where.getClass().newInstance();
//通过缓存的表字段map来插入结果
for (Map.Entry<String, Field> entry : cacheMap.entrySet())
//表字段
String columnName = entry.getKey();
//表字段对应的java变量field
Field field = entry.getValue();
//拿到表字段在游标中的位置
int columnIndex = cursor.getColumnIndex(columnName);
//如果游标中有该字段,则往下执行
if (columnIndex != -1)
//获取缓存的field对象的类型
Class<?> type = field.getType();
//获取游标查出来的结果并通过field对象set进item中
if (type == String.class)
field.set(item, cursor.getString(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 == Double.class)
field.set(item, cursor.getDouble(columnIndex));
else if (type == Float.class)
field.set(item, cursor.getFloat(columnIndex));
else if (type == byte[].class)
field.set(item, cursor.getBlob(columnIndex));
else
continue;
list.add(item);
catch (Exception e)
e.printStackTrace();
return list;
queryByAll
public class BaseDao<T> implements IBaseDao<T>
//……其他代码
/**
* 查询全部
*
* @param clazz 查询的表对应的java对象
* @return 该对象的集合
*/
public List<T> queryByAll(Class<T> clazz)
ArrayList<T> list = new ArrayList<>();
//相当于sql语句:select * from table_name
Cursor cursor = getSqLiteDatabase().rawQuery("select * from " + getTableName(), null);
//查询全部的逻辑与条件查询的逻辑一样
while (cursor.moveToNext())
try
Object item = clazz.newInstance();
for (Map.Entry<String, Field> entry : getCacheMap().entrySet())
String columnName = entry.getKey();
Field field = entry.getValue();
int columnIndex = cursor.getColumnIndex(columnName);
Class<?> type = field.getType();
if (columnIndex != -1)
if (type == String.class)
field.set(item, cursor.getString(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 == Double.class)
field.set(item, cursor.getDouble(columnIndex));
else if (type == Float.class)
field.set(item, cursor.getFloat(columnIndex));
else if (type == byte[].class)
field.set(itemAndroid数据库设计——1,面向对象(ORM)建库建表