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)建库建表

Android数据库设计——1,面向对象(ORM)建库建表

安卓中的数据库操作

5 -- Hibernate的基本用法 --1 1 对象/关系数据库映射(ORM)

orm的设计思路

Mybatis相关概念