XUtils 源码分析(三)--数据库操作模块

来源:互联网 发布:whenyoubelieve知乎 编辑:程序博客网 时间:2024/06/05 08:20

一 数据库创建


1.客户端程序:

  1. DbUtils.DaoConfig config = new DbUtils.DaoConfig(context);

  2.        config.setDbName("user.db");

  3.        mUserInforDbUtils = DbUtils.create(config);

2.DbUtils的创建函数:

  1. public static DbUtils create(DaoConfig daoConfig) {

  2.        return getInstance(daoConfig);

  3.    }

3.私有静态方法获取DbUtils实例:先检查缓存,没有就去创建。

  1. /**

  2.     * 获取一个DbUtils,首先检查Map是否有缓存,没有新建添加到Map中

  3.     */

  4.    private synchronized static DbUtils getInstance(DaoConfig daoConfig) {

  5.        DbUtils dao = daoMap.get(daoConfig.getDbName());

  6.        if (dao == null) {

  7.            dao = new DbUtils(daoConfig);//生成数据库操作对象,新建数据库

  8.            daoMap.put(daoConfig.getDbName(), dao);//存放数据库操作对象

  9.        } else {

  10.            dao.daoConfig = daoConfig;//更新配置

  11.        }

  12.        //处理数据库更新问题

  13.        SQLiteDatabase database = dao.database;

  14.        int oldVersion = database.getVersion();

  15.        int newVersion = daoConfig.getDbVersion();

  16.        if (oldVersion != newVersion) {//版本不一致

  17.            if (oldVersion != 0) {

  18.                DbUpgradeListener upgradeListener = daoConfig.getDbUpgradeListener();

  19.                if (upgradeListener != null) {

  20.                    upgradeListener.onUpgrade(dao, oldVersion, newVersion);//用户自定义更新

  21.                } else {//清空旧的数据库

  22.                    try {

  23.                        dao.dropDb();

  24.                    } catch (DbException e) {

  25.                        LogUtils.e(e.getMessage(), e);

  26.                    }

  27.                }

  28.            }

  29.            database.setVersion(newVersion);

  30.        }        return dao;

  31.    }

3.1 私有构造方法:

  1. private DbUtils(DaoConfig config) {

  2.        if (config == null) {

  3.            throw new IllegalArgumentException("daoConfig may not be null");

  4.        }

  5.        this.database = createDatabase(config);

  6.        this.daoConfig = config;

  7.    }

3.1.1 构造方法生成的数据库createDatabase(config):


  1.  /*

  2.     * 新建数据库

  3.     */

  4.    private SQLiteDatabase createDatabase(DaoConfig config) {

  5.        SQLiteDatabase result = null;

  6.        String dbDir = config.getDbDir();

  7.        if (!TextUtils.isEmpty(dbDir)) {//数据库路径不为空

  8.            File dir = new File(dbDir);

  9.            if (dir.exists() || dir.mkdirs()) {

  10.                File dbFile = new File(dbDir, config.getDbName());

  11.                result = SQLiteDatabase.openOrCreateDatabase(dbFile, null);//生成数据库文件

  12.            }

  13.        } else {//生成数据库对象

  14.            result = config.getContext().openOrCreateDatabase(config.getDbName(), 0, null);

  15.        }

  16.        return result;

  17.    }

3.2清空数据库:

  1.  /**
  2.     * 清空数据库
  3.     */
  4.    public void dropDb() throws DbException {
  5.        Cursor cursor = execQuery("SELECT name FROM sqlite_master WHERE type='table' AND name<>'sqlite_sequence'");

  6. //获得数据库中的所有表

  7.        if (cursor != null) {
  8.            try {
  9.                while (cursor.moveToNext()) {
  10.                    try {
  11.                        String tableName = cursor.getString(0);
  12.                        execNonQuery("DROP TABLE " + tableName);//清空
  13.                        Table.remove(this, tableName);
  14.                    } catch (Throwable e) {
  15.                        LogUtils.e(e.getMessage(), e);
  16.                    }
  17.                }
  18.            } catch (Throwable e) {
  19.                throw new DbException(e);
  20.            } finally {
  21.                IOUtils.closeQuietly(cursor);
  22.            }
  23.        }
  24.    }


4.客户端存储数据:

  1.   try {
  2.            mUserInforDbUtils.save(user); // 使用saveBindingId保存实体时会为实体的id赋值
  3.        } catch (DbException e) {
  4.            e.printStackTrace();
  5.        }

4.1 save函数 mUserInforDbUtils.save(user);

  1.    /**
  2.     * 数据库存储记录
  3.     */
  4.    public void save(Object entity) throws DbException {
  5.        try {
  6.            beginTransaction();//开启事务
  7.            createTableIfNotExist(entity.getClass());//检测表是否存在,不存在就新建
  8.            execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));
  9.            setTransactionSuccessful();
  10.        } finally {
  11.            endTransaction();
  12.        }
  13.    }
4.1.1 开启数据库事物管理 beginTransaction();
  1. /**
  2.     * 开启事务管理
  3.     */
  4.    private void beginTransaction() {
  5.        if (allowTransaction) {//允许开启
  6.            database.beginTransaction();
  7.        } else {//不允许锁定
  8.            writeLock.lock();
  9.            writeLocked = true;
  10.        }
  11.    }

4.1.2 表不存在就创建 createTableIfNotExist(entity.getClass());

  1.  /**
  2.     * 不存在表就新建
  3.     */
  4.    public void createTableIfNotExist(Class<?> entityType) throws DbException {
  5.        if (!tableIsExist(entityType)) {//表不存在,注意表对象已存在
  6.            SqlInfo sqlInfo = SqlInfoBuilder.buildCreateTableSqlInfo(this, entityType);//生成SQL语句对象
  7.            execNonQuery(sqlInfo);//执行语句,建表
  8.            String execAfterTableCreated = TableUtils.getExecAfterTableCreated(entityType);
  9.            if (!TextUtils.isEmpty(execAfterTableCreated)) {
  10.                execNonQuery(execAfterTableCreated);//设置表默认值
  11.            }
  12.        }
  13.    }
4.1.2.1判断表是否存在 tableIsExist(entityType);
  1.    /**
  2.     * 判断表是否存在
  3.     */
  4.    public boolean tableIsExist(Class<?> entityType) throws DbException {
  5.        Table table = Table.get(this, entityType);//根据类对象获取表
  6.        if (table.isCheckedDatabase()) {
  7.            return true;
  8.        }
  9.        Cursor cursor = execQuery("SELECT COUNT(*) AS c FROM sqlite_master WHERE type='table' AND name='" + table.tableName + "'");//查找制定表
  10.        if (cursor != null) {
  11.            try {
  12.                if (cursor.moveToNext()) {
  13.                    int count = cursor.getInt(0);
  14.                    if (count > 0) {//存在指定的表
  15.                        table.setCheckedDatabase(true);
  16.                        return true;
  17.                    }
  18.                }
  19.            } catch (Throwable e) {
  20.                throw new DbException(e);
  21.            } finally {
  22.                IOUtils.closeQuietly(cursor);
  23.            }
  24.        }
  25.        return false;
  26.    }

4.1.2.1.1 获取表对象Table.get(this, entityType);缓存中去找没有去新建

  1. /**
  2.     * 获取表
  3.     */
  4.    public static synchronized Table get(DbUtils db, Class<?> entityType) {
  5.        String tableKey = db.getDaoConfig().getDbName() + "#" + entityType.getName();

               Table table = tableMap.get(tableKey);

  1.        if (table == null) {//没有缓存
  2.            table = new Table(db, entityType);
  3.            tableMap.put(tableKey, table);
  4.        }
  5.        return table;
  6.    }

4.1.2.1.1.1 Table私有构造方法:

  1. private Table(DbUtils db, Class<?> entityType) {
  2.        this.db = db;
  3.        this.tableName = TableUtils.getTableName(entityType);//获取表名
  4.        this.id = TableUtils.getId(entityType);
  5.        this.columnMap = TableUtils.getColumnMap(entityType);//获取列MAP
  6.        finderMap = new HashMap<String, Finder>();
  7.        for (Column column : columnMap.values()) {//得到主表列对象
  8.            column.setTable(this);
  9.            if (column instanceof Finder) {
  10.                finderMap.put(column.getColumnName(), (Finder) column);
  11.            }
  12.        }
  13.    }

4.1.2.1.1.1.1 获取表名 TableUtils.getTableName(entityType);

  1. public static String getTableName(Class<?> entityType) {
  2.        Table table = entityType.getAnnotation(Table.class);
  3.        if (table == null || TextUtils.isEmpty(table.name())) {//没有注解字段Table
  4.            return entityType.getName().replace('.', '_');
  5.        }
  6.        return table.name();
  7.    }

4.1.2.1.1.1.2 获取表的列对象 TableUtils.getColumnMap(entityType);

  1. /**
  2.     * 根据类对象获取列对象的MAP
  3.     */
  4.    static synchronized HashMap<String, Column> getColumnMap(Class<?> entityType) {
  5.        if (entityColumnsMap.containsKey(entityType.getName())) {//这个类已经存储过了数据库列对象
  6.            return entityColumnsMap.get(entityType.getName());
  7.        }
  8.        HashMap<String, Column> columnMap = new HashMap<String, Column>();
  9.        String primaryKeyFieldName = getPrimaryKeyFieldName(entityType);
  10.        addColumns2Map(entityType, primaryKeyFieldName, columnMap);//缓存类对象的属性指为Columns对象
  11.        entityColumnsMap.put(entityType.getName(), columnMap);//缓存这个数据表的Columns对象MAP集
  12.        return columnMap;
  13.    }

4.1.2.1.1.1.2.1 缓存列对象addColumns2Map(entityType, primaryKeyFieldName, columnMap);

  1. /**
  2.     * 缓存类对象的属性指为Columns对象
  3.     */
  4.    private static void addColumns2Map(Class<?> entityType, String primaryKeyFieldName, HashMap<String, Column> columnMap) {
  5.        if (Object.class.equals(entityType)) return;
  6.        try {
  7.            Field[] fields = entityType.getDeclaredFields();
  8.            for (Field field : fields) {
  9.                if (ColumnUtils.isTransient(field) || Modifier.isStatic(field.getModifiers())) {//忽略static及注解Transient的属性
  10.                    continue;
  11.                }
  12.                if (ColumnConverterFactory.isSupportColumnConverter(field.getType())) {//属性字段支持列对象转换
  13.                    if (!field.getName().equals(primaryKeyFieldName)) {//不是ID字段
  14.                        Column column = new Column(entityType, field);
  15.                        if (!columnMap.containsKey(column.getColumnName())) {//缓存列对象
  16.                            columnMap.put(column.getColumnName(), column);
  17.                        }
  18.                    }
  19.                } else if (ColumnUtils.isForeign(field)) {// 属性字段是Foreign注解,从表注解
  20.                    Foreign column = new Foreign(entityType, field);
  21.                    if (!columnMap.containsKey(column.getColumnName())) {
  22.                        columnMap.put(column.getColumnName(), column);
  23.                    }
  24.                } else if (ColumnUtils.isFinder(field)) {//属性字段是Finder,主表注解
  25.                    Finder column = new Finder(entityType, field);
  26.                    if (!columnMap.containsKey(column.getColumnName())) {
  27.                        columnMap.put(column.getColumnName(), column);
  28.                    }
  29.                }
  30.            }
  31.            if (!Object.class.equals(entityType.getSuperclass())) {//继续将父类属性字段缓存
  32.                addColumns2Map(entityType.getSuperclass(), primaryKeyFieldName, columnMap);
  33.            }
  34.        } catch (Throwable e) {
  35.            LogUtils.e(e.getMessage(), e);
  36.        }
  37.    }

4.1.2.1.1.1.2.1.1 判断属性字段时候支持列对象转换

  1.    /**
  2.     * 检查是否支持Column对象转换
  3.     */
  4.    public static boolean isSupportColumnConverter(Class columnType) {
  5.        if (columnType_columnConverter_map.containsKey(columnType.getName())) {
  6.            return true;
  7.        } else if (ColumnConverter.class.isAssignableFrom(columnType)) {//isAssignableFrom如果调用这个方法的class或接口 与 参数cls表示的类或接口相同,或者是参数cls表示的类或接口的父类,则返回true。
  8.            try {
  9.                ColumnConverter columnConverter = (ColumnConverter) columnType.newInstance();
  10.                if (columnConverter != null) {
  11.                    columnType_columnConverter_map.put(columnType.getName(), columnConverter);
  12.                }
  13.                return columnConverter == null;
  14.            } catch (Throwable e) {
  15.            }
  16.        }
  17.        return false;
  18.    }

4.1.2.1.1.1.2.1.1.1 标准列对象columnType_columnConverter_map内容,上述判断的依据:

  1.   private static final ConcurrentHashMap<String, ColumnConverter> columnType_columnConverter_map;
  2.    static {
  3.        columnType_columnConverter_map = new ConcurrentHashMap<String, ColumnConverter>();
  4.        BooleanColumnConverter booleanColumnConverter = new BooleanColumnConverter();
  5.        columnType_columnConverter_map.put(boolean.class.getName(), booleanColumnConverter);
  6.        columnType_columnConverter_map.put(Boolean.class.getName(), booleanColumnConverter);
  7.        ByteArrayColumnConverter byteArrayColumnConverter = new ByteArrayColumnConverter();
  8.        columnType_columnConverter_map.put(byte[].class.getName(), byteArrayColumnConverter);
  9.        ByteColumnConverter byteColumnConverter = new ByteColumnConverter();
  10.        columnType_columnConverter_map.put(byte.class.getName(), byteColumnConverter);
  11.        columnType_columnConverter_map.put(Byte.class.getName(), byteColumnConverter);
  12.        CharColumnConverter charColumnConverter = new CharColumnConverter();
  13.        columnType_columnConverter_map.put(char.class.getName(), charColumnConverter);
  14.        columnType_columnConverter_map.put(Character.class.getName(), charColumnConverter);
  15.        DateColumnConverter dateColumnConverter = new DateColumnConverter();
  16.        columnType_columnConverter_map.put(Date.class.getName(), dateColumnConverter);
  17.        DoubleColumnConverter doubleColumnConverter = new DoubleColumnConverter();
  18.        columnType_columnConverter_map.put(double.class.getName(), doubleColumnConverter);
  19.        columnType_columnConverter_map.put(Double.class.getName(), doubleColumnConverter);
  20.        FloatColumnConverter floatColumnConverter = new FloatColumnConverter();
  21.        columnType_columnConverter_map.put(float.class.getName(), floatColumnConverter);
  22.        columnType_columnConverter_map.put(Float.class.getName(), floatColumnConverter);
  23.        IntegerColumnConverter integerColumnConverter = new IntegerColumnConverter();
  24.        columnType_columnConverter_map.put(int.class.getName(), integerColumnConverter);
  25.        columnType_columnConverter_map.put(Integer.class.getName(), integerColumnConverter);
  26.        LongColumnConverter longColumnConverter = new LongColumnConverter();
  27.        columnType_columnConverter_map.put(long.class.getName(), longColumnConverter);
  28.        columnType_columnConverter_map.put(Long.class.getName(), longColumnConverter);
  29.        ShortColumnConverter shortColumnConverter = new ShortColumnConverter();
  30.        columnType_columnConverter_map.put(short.class.getName(), shortColumnConverter);
  31.        columnType_columnConverter_map.put(Short.class.getName(), shortColumnConverter);
  32.        SqlDateColumnConverter sqlDateColumnConverter = new SqlDateColumnConverter();
  33.        columnType_columnConverter_map.put(java.sql.Date.class.getName(), sqlDateColumnConverter);
  34.        StringColumnConverter stringColumnConverter = new StringColumnConverter();
  35.        columnType_columnConverter_map.put(String.class.getName(), stringColumnConverter);
  36.    }


4.1.2.1.1.1.3 获取表的ID属性TableUtils.getId(entityType);


  1.    /**
  2.     * 获得对象的ID属性
  3.     */
  4.    static synchronized com.lidroid.xutils.db.table.Id getId(Class<?> entityType) {
  5.        if (Object.class.equals(entityType)) {
  6.            throw new RuntimeException("field 'id' not found");
  7.        }
  8.        if (entityIdMap.containsKey(entityType.getName())) {
  9.            return entityIdMap.get(entityType.getName());
  10.        }
  11.        Field primaryKeyField = null;
  12.        Field[] fields = entityType.getDeclaredFields();//获取声明字段
  13.        if (fields != null) {
  14.            for (Field field : fields) {
  15.                if (field.getAnnotation(Id.class) != null) {//获取注解ID属性
  16.                    primaryKeyField = field;
  17.                    break;
  18.                }
  19.            }
  20.            if (primaryKeyField == null) {//没有发现注解ID,根据字段生成ID
  21.                for (Field field : fields) {
  22.                    if ("id".equals(field.getName()) || "_id".equals(field.getName())) {
  23.                        primaryKeyField = field;
  24.                        break;
  25.                    }
  26.                }
  27.            }
  28.        }
  29.        if (primaryKeyField == null) {
  30.            return getId(entityType.getSuperclass());//没有iD属性再去他的父类去找
  31.        }
  32.        com.lidroid.xutils.db.table.Id id = new com.lidroid.xutils.db.table.Id(entityType, primaryKeyField);//生成数据ID对象
  33.        entityIdMap.put(entityType.getName(), id);//存储这个ID对象
  34.        return id;
  35.    }


4.1.2.1.1.1.3.1 ID构造函数:com.lidroid.xutils.db.table.Id id = new com.lidroid.xutils.db.table.Id(entityType, primaryKeyField);


  1.   Id(Class<?> entityType, Field field) {
  2.        super(entityType, field);
  3.        columnFieldClassName = columnField.getType().getName();//id属性类型名
  4.    }

4.1.2.1.1.1.3.1.1 父类构造函数super(entityType, field);

  1. Column(Class<?> entityType, Field field) {
  2.        this.columnField = field;
  3.        this.columnConverter = ColumnConverterFactory.getColumnConverter(field.getType());//获取ID属性的ColumnConverter对象
  4.        this.columnName = ColumnUtils.getColumnNameByField(field);
  5.        if (this.columnConverter != null) {
  6.            this.defaultValue = this.columnConverter.getFieldValue(ColumnUtils.getColumnDefaultValue(field));
  7.        } else {
  8.            this.defaultValue = null;
  9.        }
  10.        this.getMethod = ColumnUtils.getColumnGetMethod(entityType, field);
  11.        this.setMethod = ColumnUtils.getColumnSetMethod(entityType, field);
  12.    }

至此Table对象构造完成。接下来如果数据库中的表不存在就去创建。


4.1.2.2 去构建创建表的SQL语句 SqlInfoBuilder.buildCreateTableSqlInfo(this, entityType);

  1. public static SqlInfo buildCreateTableSqlInfo(DbUtils db, Class<?> entityType) throws DbException {
  2.        Table table = Table.get(db, entityType);
  3.        Id id = table.id;
  4.        StringBuffer sqlBuffer = new StringBuffer();//构造新建数据库SQL语句
  5.        sqlBuffer.append("CREATE TABLE IF NOT EXISTS ");
  6.        sqlBuffer.append(table.tableName);
  7.        sqlBuffer.append(" ( ");
  8.        if (id.isAutoIncrement()) {//id自增
  9.            sqlBuffer.append(""").append(id.getColumnName()).append(""  ").append("INTEGER PRIMARY KEY AUTOINCREMENT,");
  10.        } else {
  11.            sqlBuffer.append(""").append(id.getColumnName()).append(""  ").append(id.getColumnDbType()).append(" PRIMARY KEY,");
  12.        }
  13.        Collection<Column> columns = table.columnMap.values();//获取表的列对象集合
  14.        for (Column column : columns) {//组合列名
  15.            if (column instanceof Finder) {//主表
  16.                continue;
  17.            }
  18.            sqlBuffer.append(""").append(column.getColumnName()).append(""  ");//列名
  19.            sqlBuffer.append(column.getColumnDbType());//类型
  20.            if (ColumnUtils.isUnique(column.getColumnField())) {//属性
  21.                sqlBuffer.append(" UNIQUE");
  22.            }
  23.            if (ColumnUtils.isNotNull(column.getColumnField())) {
  24.                sqlBuffer.append(" NOT NULL");
  25.            }
  26.            String check = ColumnUtils.getCheck(column.getColumnField());
  27.            if (check != null) {
  28.                sqlBuffer.append(" CHECK(").append(check).append(")");
  29.            }
  30.            sqlBuffer.append(",");
  31.        }
  32.        sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);//删除
  33.        sqlBuffer.append(" )");
  34.        return new SqlInfo(sqlBuffer.toString());
  35.    }

4.1.2.3执行构建数据表的语句 execNonQuery(sqlInfo);

  1.  public void execNonQuery(SqlInfo sqlInfo) throws DbException {
  2.        debugSql(sqlInfo.getSql());
  3.        try {
  4.            if (sqlInfo.getBindArgs() != null) {
  5.                database.execSQL(sqlInfo.getSql(), sqlInfo.getBindArgsAsArray());//有占位符的执行
  6.            } else {
  7.                database.execSQL(sqlInfo.getSql());
  8.            }
  9.        } catch (Throwable e) {
  10.            throw new DbException(e);
  11.        }
  12.    }
4.1.2.4 表构建完成时如果有注解去设置表的默认值String execAfterTableCreated = TableUtils.getExecAfterTableCreated(entityType);
  1. /**
  2.     * 获取表注解默认值
  3.     */
  4.    public static String getExecAfterTableCreated(Class<?> entityType) {
  5.        Table table = entityType.getAnnotation(Table.class);
  6.        if (table != null) {
  7.            return table.execAfterTableCreated();
  8.        }
  9.        return null;
  10.    }

4.1.2.5 如果这个默认值语句不为空去执行,设置默认值execNonQuery(execAfterTableCreated);即调用4.1.2.3函数。


至此,对于数据表如果不存在就去创建操作完成。


4.1.3 去构造插入的SQL语句SqlInfoBuilder.buildInsertSqlInfo(this, entity);

  1.    public static SqlInfo buildInsertSqlInfo(DbUtils db, Object entity) throws DbException {
  2.        List<KeyValue> keyValueList = entity2KeyValueList(db, entity);
  3.        if (keyValueList.size() == 0) return null;
  4.        SqlInfo result = new SqlInfo();
  5.        StringBuffer sqlBuffer = new StringBuffer();
  6.        sqlBuffer.append("INSERT INTO ");
  7.        sqlBuffer.append(TableUtils.getTableName(entity.getClass()));//表名
  8.        sqlBuffer.append(" (");
  9.        for (KeyValue kv : keyValueList) {//封装插入的实体键值对
  10.            sqlBuffer.append(kv.key).append(",");
  11.            result.addBindArgWithoutConverter(kv.value);//添加到属性链表中
  12.        }
  13.        sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
  14.        sqlBuffer.append(") VALUES (");
  15.        int length = keyValueList.size();
  16.        for (int i = 0; i < length; i++) {
  17.            sqlBuffer.append("?,");
  18.        }
  19.        sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
  20.        sqlBuffer.append(")");
  21.        result.setSql(sqlBuffer.toString());
  22.        return result;
  23.    }

4.1.4 执行SQL语句执行插入数据操作 execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));即调用4.1.2.3函数。

4.1.5 设置数据库事务提交成功setTransactionSuccessful();

  1. private void setTransactionSuccessful() {
  2.        if (allowTransaction) {
  3.            database.setTransactionSuccessful();
  4.        }
  5.    }

至此,数据库插入一条记录完成。

  


5.客户端存储List数据

  1. try {
  2.            mUserFriendDbUtils.saveAll(friends);
  3.        } catch (DbException e) {
  4.            e.printStackTrace();
  5.        }

5.1 存储List数据saveAll

  1. public void saveAll(List<?> entities) throws DbException {
  2.        if (entities == null || entities.size() == 0) return;
  3.        try {
  4.            beginTransaction();//开启事务
  5.            createTableIfNotExist(entities.get(0).getClass());
  6.            for (Object entity : entities) {
  7.                execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));
  8.            }
  9.            setTransactionSuccessful();
  10.        } finally {
  11.            endTransaction();
  12.        }
  13.    }
5.1.1 构造插入语句调用4.1.2.3函数SqlInfoBuilder.buildInsertSqlInfo(this, entity)


后续与上述单项插入相同。



删除数据操作。deleteAll;

6 客户端删除操作

  1. try {
  2.            mUserCircleDbUtils.deleteAll(Circle.class);
  3.        } catch (DbException e) {
  4.            e.printStackTrace();
  5.        }

6.1 执行删除mUserCircleDbUtils.deleteAll(Circle.class);


  1. public void deleteAll(Class<?> entityType) throws DbException {
  2.        delete(entityType, null);
  3.    }

6.1.1 调用delete(entityType, null);先判断表是否存在,在开启事务管理,执行SQL语句,提交事务成功,关闭事务。


  1.  public void delete(Class<?> entityType, WhereBuilder whereBuilder) throws DbException {
  2.        if (!tableIsExist(entityType)) return;
  3.        try {
  4.            beginTransaction();
  5.            execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, whereBuilder));
  6.            setTransactionSuccessful();
  7.        } finally {
  8.            endTransaction();
  9.        }
  10.    }

6.1.1.1 构造删除的SQL语句SqlInfoBuilder.buildDeleteSqlInfo(this, entityType, whereBuilder);

  1. public static SqlInfo buildDeleteSqlInfo(DbUtils db, Class<?> entityType, WhereBuilder whereBuilder) throws DbException {
  2.        Table table = Table.get(db, entityType);//获取表对象
  3.        StringBuilder sb = new StringBuilder(buildDeleteSqlByTableName(table.tableName));
  4.        if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) {
  5.            sb.append(" WHERE ").append(whereBuilder.toString());
  6.        }
  7.        return new SqlInfo(sb.toString());
  8.    }

6.1.1.1.1根据表名构造删除SQL语句buildDeleteSqlByTableName(table.tableName)

  1.   private static String buildDeleteSqlByTableName(String tableName) {
  2.        return "DELETE FROM " + tableName;
  3.    }

接下来执行与前面相同。

至此deleteAll操作完成。


查找findAll操作:


7 客户端findAll操作:

  1.   try {
  2.            userList = mUserInforDbUtils.findAll(User.class);
  3.        } catch (DbException e) {
  4.            e.printStackTrace();
  5.        }

7.1查找操作;

  1. public <T> List<T> findAll(Class<T> entityType) throws DbException {
  2.        return findAll(Selector.from(entityType));
  3.    }
7.1.1 调用findAll操作;
  1. public <T> List<T> findAll(Selector selector) throws DbException {
  2.        if (!tableIsExist(selector.getEntityType())) return null;
  3.        String sql = selector.toString();//构造选择语句
  4.        long seq = CursorUtils.FindCacheSequence.getSeq();
  5.        findTempCache.setSeq(seq);//
  6.        Object obj = findTempCache.get(sql);
  7.        if (obj != null) {//存在缓存
  8.            return (List<T>) obj;
  9.        }
  10.        List<T> result = new ArrayList<T>();
  11.        Cursor cursor = execQuery(sql);//不存在缓存去执行查询吧
  12.        if (cursor != null) {
  13.            try {
  14.                while (cursor.moveToNext()) {//存储
  15.                    T entity = (T) CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq);//////////
  16.                    result.add(entity);
  17.                }
  18.                findTempCache.put(sql, result);
  19.            } catch (Throwable e) {
  20.                throw new DbException(e);
  21.            } finally {
  22.                IOUtils.closeQuietly(cursor);
  23.            }
  24.        }
  25.        return result;
  26.    }
7.1.1.1生产Selector语句selector.toString();
  1. @Override
  2.    public String toString() {
  3.        StringBuilder result = new StringBuilder();
  4.        result.append("SELECT ");
  5.        result.append("*");
  6.        result.append(" FROM ").append(tableName);
  7.        if (whereBuilder != null && whereBuilder.getWhereItemSize() > 0) {
  8.            result.append(" WHERE ").append(whereBuilder.toString());
  9.        }
  10.        if (orderByList != null) {
  11.            for (int i = 0; i < orderByList.size(); i++) {
  12.                result.append(" ORDER BY ").append(orderByList.get(i).toString());
  13.            }
  14.        }
  15.        if (limit > 0) {
  16.            result.append(" LIMIT ").append(limit);
  17.            result.append(" OFFSET ").append(offset);
  18.        }
  19.        return result.toString();
  20.    }

7.1.1.1.1执行查找语句获得查找的数据CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq);

  1.  public static <T> T getEntity(final DbUtils db, final Cursor cursor, Class<T> entityType, long findCacheSequence) {
  2.        if (db == null || cursor == null) return null;
  3.        EntityTempCache.setSeq(findCacheSequence);
  4.        try {
  5.            Table table = Table.get(db, entityType);
  6.            Id id = table.id;
  7.            String idColumnName = id.getColumnName();
  8.            int idIndex = id.getIndex();
  9.            if (idIndex < 0) {
  10.                idIndex = cursor.getColumnIndex(idColumnName);
  11.            }
  12.            Object idValue = id.getColumnConverter().getFieldValue(cursor, idIndex);
  13.            T entity = EntityTempCache.get(entityType, idValue);
  14.            if (entity == null) {
  15.                entity = entityType.newInstance();
  16.                id.setValue2Entity(entity, cursor, idIndex);
  17.                EntityTempCache.put(entityType, idValue, entity);
  18.            } else {
  19.                return entity;
  20.            }
  21.            int columnCount = cursor.getColumnCount();
  22.            for (int i = 0; i < columnCount; i++) {
  23.                String columnName = cursor.getColumnName(i);
  24.                Column column = table.columnMap.get(columnName);
  25.                if (column != null) {
  26.                    column.setValue2Entity(entity, cursor, i);
  27.                }
  28.            }
  29.            // init finder
  30.            for (Finder finder : table.finderMap.values()) {
  31.                finder.setValue2Entity(entity, null, 0);
  32.            }
  33.            return entity;
  34.        } catch (Throwable e) {
  35.            LogUtils.e(e.getMessage(), e);
  36.        }
  37.        return null;
  38.    }

执行完查询之后缓存并返回结果。


更新操作

8 客户端调用更新

  1. try {
  2.            mArticleDbUtils.update(acceptArticle, "zanCount");
  3.        } catch (DbException e) {
  4.            e.printStackTrace();
  5.        }

8.1 函数update

  1. public void update(Object entity, String... updateColumnNames) throws DbException {
  2.        if (!tableIsExist(entity.getClass())) return;
  3.        try {
  4.            beginTransaction();
  5.            execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames));
  6.            setTransactionSuccessful();
  7.        } finally {
  8.            endTransaction();
  9.        }
  10.    }

8.1.1构造更新SQL语句SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames)

  1. public static SqlInfo buildUpdateSqlInfo(DbUtils db, Object entity, String... updateColumnNames) throws DbException {
  2.        List<KeyValue> keyValueList = entity2KeyValueList(db, entity);
  3.        if (keyValueList.size() == 0) return null;
  4.        HashSet<String> updateColumnNameSet = null;
  5.        if (updateColumnNames != null && updateColumnNames.length > 0) {
  6.            updateColumnNameSet = new HashSet<String>(updateColumnNames.length);
  7.            Collections.addAll(updateColumnNameSet, updateColumnNames);
  8.        }
  9.        Class<?> entityType = entity.getClass();
  10.        Table table = Table.get(db, entityType);
  11.        Id id = table.id;
  12.        Object idValue = id.getColumnValue(entity);
  13.        if (null == idValue) {
  14.            throw new DbException("this entity[" + entity.getClass() + "]'s id value is null");
  15.        }
  16.        SqlInfo result = new SqlInfo();
  17.        StringBuffer sqlBuffer = new StringBuffer("UPDATE ");
  18.        sqlBuffer.append(table.tableName);
  19.        sqlBuffer.append(" SET ");
  20.        for (KeyValue kv : keyValueList) {
  21.            if (updateColumnNameSet == null || updateColumnNameSet.contains(kv.key)) {
  22.                sqlBuffer.append(kv.key).append("=?,");
  23.                result.addBindArgWithoutConverter(kv.value);
  24.            }
  25.        }
  26.        sqlBuffer.deleteCharAt(sqlBuffer.length() - 1);
  27.        sqlBuffer.append(" WHERE ").append(WhereBuilder.b(id.getColumnName(), "=", idValue));
  28.        result.setSql(sqlBuffer.toString());
  29.        return result;
  30.    }

后续操作与前面相同,支持更新操作完成。

二 致敬原作者,谢谢作者辛苦付出,代码受益匪浅。

传送门

三 其他讲解:

架构讲解:传送门

四 源码注释

源码详细注释:传送门



0 0