Android数据库面向对象之增、删、改、查

关于数据库等封装之前有写过一篇博客Android数据库面向对象之增、删、改、查这篇博客写的是将数据库存储在sd卡中,android6.0以后关于sd卡的操作就需要动态申请权限,如果在工具类中使用时权限的申请就没有那么方便,即使在activity或者fragment中时候,使用的频次比较高时,老是申请权限也比较麻烦,存储在data目录下虽然存储的数据大小有限,但是不需要去做权限的申请,使用起来方便很多,这里是针对data目录下的存储的封装,基本上和sd卡的存储封装大同小异,有些细微的变化。

系统提供了SQLiteOpenHelper这个类用于数据的创建和数据库的版本管理,在使用是extends SQLiteOpenHelper该类,会要求去重写onCreate()方法和onUpgrade()方法,在数据创建时会回调onCreate()方法,数据库版本更新是会回调onUpgrade()方法;

public class MySqliteHelper extends SQLiteOpenHelper {
    private BaseDao baseDao;

    public MySqliteHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
    }

    public MySqliteHelper(Context context) {
        super(context, ConstantValue.DATABASE_NAME, null, ConstantValue.DATABASE_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        //执行建表语句
        db.execSQL(baseDao.createTable());
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //数据库版本变动会回调这里
    }

    public synchronized , M> T
    getDataHelper(Class clazz, Class entityClass) {
        try {
            //利用反射实例化BaseDao
            baseDao = clazz.newInstance();
            //初始化BaseDao中的参数
            baseDao.init(entityClass);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T) baseDao;
    }
}

MySqliteHelper弄好后,需要定义一个接口提供数据库增删改查操作的一系列方法;

public interface IBaseDao {
    /**
     * 插入数据库
     * @param entity  插入的数据对象
     * @return
     */
    Long insert(T entity);
    /**
     * 批量插入数据库
     * @param entity 插入的数据对象
     * @return
     */
    void insert(List entity);

    /**
     * 更新数据库
     * @return
     */
    int update(ContentValues contentValues, String whereClause, String[] whereArgs);

    /**
     * 删除数据库
     * @return
     */
    int delete(String selection,String[] selectionArgs);

    /**
     * 查询数据
     * @param where  查询条件
     * @return
     */
    List query(T where);

    /**
     * 查询数据
     * @param where  查询条件
     * @param orderBy  查询排序
     * @param startIndex  开始的位置
     * @param limit  查询限制条件
     * @return
     */
    List query(T where, String selection, String[] selectionArgs, String orderBy, Integer startIndex, Integer limit);

    /**
     * 查询数据 用于多条件查询
     * @param sql  查询语句
     * @return
     */
    List query(String sql);
}

数据增删改查接口定义好了,需要一个实现类去做具体的增删改查的逻辑;

public abstract class BaseDao implements IBaseDao {
    private static volatile MySqliteHelper helper;
    private boolean isInit = false;
    private Class entityClass;
    private SQLiteDatabase database;
    private String tableName;
    /**
     * 维护这表名与成员变量名的映射关系
     * key---》表名
     * value --》Field
     */
    private HashMap cacheMap;

    public static MySqliteHelper getInstance(Context context) {
        if (helper == null) {
            synchronized (MySqliteHelper.class) {
                if (helper == null) {
                    helper = new MySqliteHelper(context.getApplicationContext());
                }
            }
        }
        return helper;
    }

    protected synchronized boolean init(Class entity) {
        if (!isInit) {
            entityClass = entity;
            //getReadableDatabase  getWritableDatabase 创建或者打开数据库
            //如果数据库不存在则会创建数据库,如果数据库存在直接打开数据库
            //默认情况下都是打开或者创建可读可写的数据库,如果磁盘已盘就是可读数据库
            database = helper.getWritableDatabase();
            //判断数据库是否打开
            if (!database.isOpen()) {
                return false;
            }
            tableName = getTableName();
            cacheMap = new HashMap<>();
            //缓存维护映射关系
            initCacheMap();
            isInit = true;
        }
        return isInit;
    }

    /**
     * 维护映射关系
     */
    private void initCacheMap() {
        String sql = "select * from " + this.tableName + " limit 1 , 0";
        Cursor cursor = null;
        try {
            cursor = database.rawQuery(sql, null);
            //表的列名数组
            String[] columnNames = cursor.getColumnNames();
            //拿到Filed数组
            Field[] colmunFields = entityClass.getFields();
            for (Field filed : colmunFields) {
                //设置私有可以访问
                filed.setAccessible(true);
            }
            //开始找对应关系
            for (String columnName : columnNames) {
                //如果找到对应的Field就赋值给他
                Field columnFiled = null;
                for (Field filed : colmunFields) {
                    String filedName = "";
                    if (filed.getAnnotation(DbFiled.class) != null) {
                        filedName = filed.getAnnotation(DbFiled.class).value();
                    } else {
                        filedName = filed.getName();
                    }
                    //如果表的列名等于了成员变量的注解名字
                    if (columnName.equals(filedName)) {
                        columnFiled = filed;
                        break;
                    }
                }
                //找到了对应关系
                if (columnFiled != null) {
                    cacheMap.put(columnName, columnFiled);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭游标
            cursor.close();
        }
        Log.e("cacheMap--->", cacheMap.size() + "");
    }

    @Override
    public Long insert(T entity) {
        Map map = getValues(entity);
        ContentValues values = getContentValues(map);
        Long insert = database.insert(tableName, null, values);
        return insert;
    }

    @Override
    public void insert(List entity) {
        //批量插入采用事务
        database.beginTransaction();
        for (T data : entity) {
            insert(data);
        }
        database.setTransactionSuccessful();
        database.endTransaction();
    }

    @Override
    public int update(ContentValues contentValues, String whereClause, String[] whereArgs) {
        int result = -1;
        result = database.update(tableName, contentValues, whereClause, whereArgs);
        return result;
    }

    @Override
    public int delete(String selection, String[] selectionArgs) {
        int result = database.delete(tableName, selection, selectionArgs);
        return result;
    }

    @Override
    public List query(T where) {
        return query(where, null, null, null, null, null);
    }

    @Override
    public List query(T where, String selection, String[] selectionArgs, String orderBy, Integer startIndex, Integer limit) {
        String limitString = "";
        if (startIndex != null && limit != null) {
            limitString = startIndex + " , " + limit;
        }
        Cursor cursor = database.query(tableName, null, selection, selectionArgs,
                null, null, orderBy, limitString);
        List result = getResult(cursor, where);
        //关闭游标
        cursor.close();
        return result;
    }

    @Override
    public List query(String sql) {
        return null;
    }

    /**
     * 根据查询条件获取查询结果
     *
     * @param cursor 数据库游标
     * @param where  查询条件
     * @return 根据查询条件返回的结果
     */
    private List getResult(Cursor cursor, T where) {
        List list = new ArrayList();
        Object item;
        while (cursor.moveToNext()) {
            try {
                item = where.getClass().newInstance();
                //遍历缓存的映射关系
                Iterator> iterator = cacheMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry entry = iterator.next();
                    //得到列名
                    String colomunName = entry.getKey();
                    //然后以列名拿到 列名在游标的位置
                    Integer columnIndex = cursor.getColumnIndex(colomunName);
                    Field field = entry.getValue();
                    Class type = field.getType();
                    if (columnIndex != -1) {
                        //反射赋值
                        if (type == String.class) {
                            field.set(item, cursor.getString(columnIndex));
                        } else if (type == Integer.class || type == int.class) {
                            field.set(item, cursor.getInt(columnIndex));
                        } else if (type == Double.class || type == double.class) {
                            field.set(item, cursor.getDouble(columnIndex));
                        } else if (type == Long.class || 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 (Exception e) {
                e.printStackTrace();
            }
        }
        return list;
    }

    /**
     * 将缓存的map数据转成ContentValues
     *
     * @param map
     * @return
     */
    private ContentValues getContentValues(Map map) {
        ContentValues contentValues = new ContentValues();
        Set keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()) {
            String key = iterator.next();
            String value = map.get(key);
            if (value != null) {
                contentValues.put(key, value);
            }
        }
        return contentValues;
    }

    /**
     * 根据数据对象和数据库表字段,将数据转成key value的形式
     *
     * @param entity 数据对象
     * @return 转换后获取到的数据
     */
    private Map getValues(T entity) {
        Map result = new HashMap<>();
        //遍历缓存数据,并进行映射
        Iterator fieldIterator = cacheMap.values().iterator();
        while (fieldIterator.hasNext()) {
            Field colmunToFiled = fieldIterator.next();
            String cacheKey = "";
            String cacheValue = "";
            if (colmunToFiled.getAnnotation(DbFiled.class) != null) {
                cacheKey = colmunToFiled.getAnnotation(DbFiled.class).value();
            } else {
                cacheKey = colmunToFiled.getName();
            }
            try {
                if (null == colmunToFiled.get(entity)) {
                    continue;
                }
                cacheValue = colmunToFiled.get(entity).toString();
            } catch (Exception e) {
                e.printStackTrace();
            }
            result.put(cacheKey, cacheValue);
        }
        return result;
    }

    /**
     * 创建表语句
     *
     * @return
     */
    public abstract String createTable();

    /**
     * 表名
     *
     * @return
     */
    public abstract String getTableName();
}

在实现类中提供了createTable()和getTableName()两个抽象方法,具体的创建表语句和表名需要根据实际的由子类去实现;

public class PersonDao extends BaseDao {
    @Override
    public String createTable() {
        String sql = "create table if not exists " + getTableName() + "(" + ConstantValue._ID + " Integer primary key," + ConstantValue.NAME + " varchar(10)," + ConstantValue.AGE + " Integer)";
        return sql;
    }

    @Override
    public String getTableName() {
        return ConstantValue.TABLE_NAME;
    }
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbFiled {
    String value();
}
public class ConstantValue {
    //数据库库版本
    public static final int DATABASE_VERSION = 1;
    public static final String DATABASE_NAME = "name.db";
    //表名
    public static final String TABLE_NAME = "person";
    //数据库存储字段
    public static final String _ID = "_id";
    public static final String NAME = "name";
    public static final String AGE = "age";
}

接下来调用下增删改查方法,看下实现的如何,在使用之前需要先初始化MySqliteHelper和创建BaseDao对象;

private PersonDao dataHelper = BaseDao.getInstance(this).getDataHelper(PersonDao.class, Person.class);

初始化完毕后就可以调用相应的方法,进行数据库操作了,先看下单条数据的插入;

/**
     * 插入数据库
     *
     * @param view
     */
    public void addDB(View view) {
        Person person = new Person();
        person._id = 100;
        person.name = "张国焘";
        person.age = 89;
        dataHelper.insert(person);
    }

利用Sqlite数据库工具打开,单条数据插入成功;
Android数据库面向对象之增、删、改、查_第1张图片

/**
     * 批量插入数据库
     *
     * @param view
     */
    public void addMoreDB(View view) {
        List list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Person person = new Person();
            person._id = i;
            person.name = "张国焘" + i;
            person.age = i;
            list.add(person);
        }
        dataHelper.insert(list);
    }

批量数据也插入到数据中了;
Android数据库面向对象之增、删、改、查_第2张图片

/**
     * 修改数据
     *
     * @param view
     */
    public void updateDB(View view) {
        ContentValues contentValues = new ContentValues();
        contentValues.put(ConstantValue.NAME, "李四8");
        String where = ConstantValue.NAME + "=?";
        String[] whereArgs = new String[]{"张国焘7"};
        dataHelper.update(contentValues, where, whereArgs);
    }

Android数据库面向对象之增、删、改、查_第3张图片
第八条数据修改成功;

/**
     * 删除数据
     *
     * @param view
     */
    public void deleteDB(View view) {
        String where = ConstantValue.NAME + "=?";
        String[] selectionArgs = new String[]{"张国焘5"};
        dataHelper.delete(where, selectionArgs);
    }

Android数据库面向对象之增、删、改、查_第4张图片
第六条数据被删除了;

/**
     * 查询数据库
     *
     * @param view
     */
    public void queryDB(View view) {
        Person user = new Person();
        user.name = "张国焘1";
        List query = dataHelper.query(user);
        Log.e("TAG", "数据库查询数据" + query.size());
        for (Person user1 : query) {
            Log.e("TAG", "姓名:" + user1.name + "年龄:" + user1.age);
        }
    }

Android数据库面向对象之增、删、改、查_第5张图片
Android数据库面向对象之增、删、改、查_第6张图片

/**
     * 分页查询
     * @param view
     */
    public void queryByLimit(View view){
        Person user = new Person();
        user.name = "张国焘1";
        List query = dataHelper.query(user,null,null,null,0,8);
        Log.e("TAG", "数据库查询数据" + query.size());
        for (Person user1 : query) {
            Log.e("TAG", "姓名:" + user1.name + "年龄:" + user1.age);
        }
    }

源码地址

你可能感兴趣的:(数据库)