搭建自己的SQLiteDataBase框架(-)

标签(空格分隔): 未分类


为了提升自身的技能,有些时候就不能总依赖第三方的开源,虽然那些大牛写出来的东西很好用,但是对自身技能包却没有多大提升。所以还是决定写一下自己的DB框架,虽然写的不好,但是会提高自己的数据库操作技能,同时还能锻炼架构能力,实现从0到1的渐变。

废话不多说,直接开始吧。

  • 需求分析
    1. 建表
    2. CRUD,即增删改查
    3. 关联关系,一对一,一对多,没有表结构的对象存储

  • 功能实现
  1. 建表
    简单的建表语句,相信只要对数据库有所了解的人都会
class Developer{
    private String id;
    private String name;
    private int age;
}
建表SQL:
create table if not exists developer([id] TEXT primary key,[name] TEXT,[age] Integer)

从这个简单的例子,我们就能分析出,建表所需要的元素。
需要表名,表字段,字段类型,如果我们依据实体模型建表,便于同实体模型一一对应,采用实体类名作为表名,类属性作为表字段。
因此,第一步功能:获取表名,字段名,字段类型
为了方便,这里引入注解辅助建表

//表注解,获取表名
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table{
    String name();
}

//字段注解,确定主键,字段名,字段类型
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column{
    //确定主键
    boolean id() default false;
    //字段名
    String name() default "";
    //字段类型
    ColumnType type() default UNKNOW;
    public enum ColumnType{
         TONE, TMANY, SERIALIZABLE, UNKNOW
    }

}

所以引入注解后的Developer.java如下

@Table(name="developer")
class Developer{
    @Column(id = true)
    private String id;
    @Column
    private String name;
    @Column
    private int age;
}

下面要做的就是利用反射机制,获取需要的元素
(1). 获取表名

public static String getTableName(Class<?> clz) {
        if (clz.isAnnotationPresent(Table.class)) {
            String name = clz.getAnnotation(Table.class).name();
            //判断非空
            if (TextUtils.isValidate(name)) {
                return name;
            } else {
                return clz.getSimpleName().toLowerCase();
            }
        }
        throw new IllegalArgumentException("the class " + clz.getSimpleName() + " can't map to the table");
    }

此时建表语句,我们就进行到了

create table if not exists getTableName(xx)(..?..)

下一步自然就是确定主键,字段名,字段类型

//确定主键
    public static String getIDColumnName(Class<?> clz) {
        if (!clz.isAnnotationPresent(Table.class)) {
            return null;
        }
        Field[] fields = clz.getDeclaredFields();
        Column column = null;
        for (Field field : fields) {
            if (field.isAnnotationPresent(Column.class)) {
                column = field.getAnnotation(Column.class);
                if (column.id()) {
                    String id = column.value();
                    if (!TextUtils.isValidate(id)) {
                        id = field.getName();
                    }
                    return id;
                }
            }
        }
        return null;

    }

    //确定字段名,字段类型
    public static String getOneColumnStmt(Field field) {
        if (field.isAnnotationPresent(Column.class)) {
            Column column = field.getAnnotation(Column.class);
            //字段名
            String name = column.name();
            //加[]防止关键字冲突
            if (!TextUtils.isValidate(name)) {
                name = "[" + field.getName() + "]";
            } else {
                name = "[" + name + "]";
            }
            String type = null;
            Class<?> clz = field.getType();
            //确定字段类型
            if (clz == String.class) {
                type = " TEXT ";
            } else if (clz == int.class || clz == Integer.class) {
                type = " Integer ";
            } else {
              //TODO 
            }
            name += type;
            if (column.id()) {
                name += " primary key ";
            }
            return name;
        }
        return "";
    }

拼接建表语句

private static String getCreateTableStmt(Class<?> clz) {
        StringBuilder mColumnStmts = new StringBuilder();
        mColumnStmts.append("create table if not exists ").append(getTableName(clz)).append(" ( ");
        if (clz.isAnnotationPresent(Table.class)) {
            Field[] fields = clz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].isAnnotationPresent(Column.class)) {
                    mColumnStmts.append(getOneColumnStmt(fields[i]));
                    mColumnStmts.append(",");
                }
            }
            if (mColumnStmts.length() > 0) {
                mColumnStmts.delete(mColumnStmts.length() - 2, mColumnStmts.length());
            }
        }
        mColumnStmts.append(")");
        return mColumnStmts.toString();
    }

测试结果如下:

11-16 15:12:56.791: I/System.out(2076): create table if not exists developer ( [age] Integer ,[id] TEXT  primary key ,[name] TEXT )

删表语句:

delete table if exists developer;

建表:利用android提供的SQLiteOpenHelper进行建表删表

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DB_NAME = "stay4it.db";
    public static final int DB_VERSION = 1;

    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

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

    @Override
    public void onCreate(SQLiteDatabase db) {
        DBUtils.createTable(db, Developer.class);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        DBUtils.dropTable(db, Developer.class);
    }

}


至此,简单的建表就完成了。