Android应用开发技巧之更方便的使用Sqlite

做应用的大多离不开数据库的支持,但是就是这么常用的对象,你有没有想过让他更方便的使用呢?什么是更方便,我的定义就是不用在每次需要用它的时候对SQL语句做过多的关心,我们应该更多的关心每一个字段的含义;也就是我们应用开发更多的关心应该在业务上,而不是在SQL语句的拼接中。
因此本人要带领大家从0到1到开始一步步优化SQLite的使用。
整体思路如下:
首先,对于SQL语句,我们发现他是不是很有规律,因此在SQL的拼接上完全可以实现部分自动化;
其次,我们应该直接将数据库字段实体类和数据库的建表,查询等关联起来;这样,我们才能最大化的达到资源的复用。
因此我结合Java的相关知识设计如下:
首先,我们必须继承SQLiteOpenHelper来实现一个建库建表的基类;
代码如下:

/**
* @author 徐晔
* @note 数据库操作类
*/
@SuppressWarnings(“rawtypes”)
public class XYDBhelper extends SQLiteOpenHelper {

private List<Class<? extends XYCreatMethod>> clslist = new ArrayList<Class<? extends XYCreatMethod>>();
private XYversionchange xYversionchange;

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

public void setXYversionchange(XYversionchange xYversionchange) {
    this.xYversionchange = xYversionchange;
}

/**
 * 添加想要建表的类
 * 
 * @param cMethord
 */
public void addCreatMethord(Class<? extends XYCreatMethod> cls) {
    if (cls != null) {
        clslist.add(cls);
    }
}

@Override
public void onCreate(SQLiteDatabase db) {
    // 利用反射机制来建立表格
    db.beginTransaction();
    try {
        for (Class<? extends XYCreatMethod> cls : clslist) {
            Constructor[] constructors = cls.getDeclaredConstructors();
            AccessibleObject.setAccessible(constructors, true);
            for (Constructor con : constructors) {
                if (con.isAccessible()) {
                    Object classObject = con.newInstance();
                    Method method = cls
                            .getMethod(XYCreatMethod.CREATTABLEMETHORD_NAME);
                    String creatsql = (String) method.invoke(classObject);
                    db.execSQL(creatsql);
                }
            }
        }
        db.setTransactionSuccessful();

    } catch (Exception e) {
        e.printStackTrace();
    }finally{
                db.endTransaction();
    }
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (xYversionchange != null) {
        xYversionchange.onUpgrade(db, oldVersion, newVersion);
    }

}

@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    if (xYversionchange != null) {
        xYversionchange.onDowngrade(db, oldVersion, newVersion);
    }

}

}
我将里面的建表语句利用反射机制实现,将建表语句的实现延迟实现,为我们下一步做一个准备。
再看看这里面牵扯到的两个类:
/**
*
* @author 徐晔 需要建表实现的接口
*/
abstract public class XYCreatMethod {
/* 获取建立表格的SQL语句 /
abstract public String getcreattablesql();

/** 建立表格方法名,利于DBhelper进行建立表格操作 */
public final static String CREATTABLEMETHORD_NAME = "getcreattablesql";

}
/**
*
* @author xuye
* @not 版本号变化时需要实现的接口方法
*/
public interface XYversionchange {
/* 版本升级时 /
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);

/** 版本降级时 */
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion);

}
这两个一个是建表语句需要继承的基类,一个是版本发生升级或者降级需要执行的方法。
在此我们可以直接将所有需要建立表格的语句继承XYCreatMethod类实现,这里就是一个灵活的地方,我们可以按照传统的实现方法,也可以自己在getcreattablesql()方法里面玩一些猫腻;
如果要将字段实体类和建表结合起来,那么可以利用注解的特点结合反射的特点来实现,我的实现如下:
首先自定义一个类的注解类:
@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取
@Target(ElementType.TYPE)//目标是接口、类、枚举、注解
@Documented//文档生成时,该注解将被包
public @interface XYTable {

/**表名字*/
public String tablename() default "className";
/** 唯一约束,指定某列和几列组合的数据不能重复 */
public String[]  unique() default "";
/**主键约束,指定某列的数据不能重复、唯*/
public String  primary_key() default "id";
/**主键的类型*/
public String primary_key_type() default "integer";
/**主键是否自增*/
public boolean is_auto_increase_primarykey() default false;
/**主键是否非空*/
public boolean primary_notnull() default true;

/**外键,指定该列记录属于主表中的一条记录,参照另一条数据 */
public String  foreign_key() default "";
/**检查,指定一个表达式,用于检验指定数据 */
public String  check() default "";

}
在定义一个字段的注解类:

@Retention(RetentionPolicy.RUNTIME)//注解会在class中存在,运行时可通过反射获取  
@Target(ElementType.FIELD)//目标是字段
@Documented//文档生成时,该注解将被包
public @interface XYTableField {
    /**是什么类型的字段 */
    public String  Type() default "varchar";
    /**非空约束 */
    public boolean  not_null() default false;
}

然后是将带有注解的字段表和字段和建表语句结合起来的方法:
/**
* @author 徐晔
* 利用反射机制进行建立表操作
*/
public class XYBaseCreatMethod extends XYCreatMethod {

private Class<?> cls;
public XYBaseCreatMethod(Class<?> cls){
    this.cls=cls;
}

@Override
public String getcreattablesql() {
    try {
        return getcreattablesql(cls);
    } catch (Exception e) {
        e.printStackTrace();
        return "";
    }
}

/**
 * 获取建表SQL
 * @param cls
 * @return
 * @throws NullPointerException
 */
public String getcreattablesql(Class<?> cls) throws NullPointerException{
    StringBuilder mBuilder = new StringBuilder();
    XYTable table = cls.getAnnotation(XYTable.class);
    if (table == null || table.tablename() == null) {
        throw new NullPointerException("没有添加应该有的数据库注释");
    }
    mBuilder.append("create table " + table.tablename());
    mBuilder.append("(" + table.primary_key() + " "
            + table.primary_key_type() + " primary key");
    if (table.is_auto_increase_primarykey()) {
        mBuilder.append(" autoincrement");
    }
    if(table.primary_notnull()){
        mBuilder.append(" not null");
    }
    mBuilder.append(",");
    for (Field field : cls.getFields()) {
        XYTableField mField = field.getAnnotation(XYTableField.class);
        if (mField == null || mField.Type() == null
                || mField.Type().length() == 0) {
            continue;
        }
        String name = field.getName();
        mBuilder.append(name);
        mBuilder.append(" " + mField.Type());
        if(mField.not_null()){
            mBuilder.append(" not null");
        }
        mBuilder.append(",");
    }
    if (table.unique() == null || table.unique().length == 0) {
        mBuilder.deleteCharAt(mBuilder.length() - 1);
    } else {
        mBuilder.append("unique(");
        for (String fie : table.unique()) {
            mBuilder.append(fie + ",");
        }
        mBuilder.deleteCharAt(mBuilder.length() - 1);
        mBuilder.append(")");
    }
    mBuilder.append(")");
    return mBuilder.toString();

}

}
下面举一个字段实体类的例子:

/**
 * @author 徐晔
 */
@XYTable(tablename = "DownloadHsitory", primary_key = "id", foreign_key = "", unique = { "url" }, is_auto_increase_primarykey = true, primary_notnull = true)
public class DownloadHsitory {
    /**
     * 下载地址
     * 
     * @note
     * */
    @XYTableField(Type = "varchar", not_null = true)
    public String url;
    /**
     * 下载文件存储的绝对路径
     * 
     * @note
     * */
    @XYTableField(Type = "varchar", not_null = true)
    public String savepath;
    /**
     * 已经下载的文件大小
     * 
     * @note
     * */
    @XYTableField(Type = "integer", not_null = true)
    public long downlength;
    /**
     * 整个文件的大小
     * 
     * @note
     * */
    @XYTableField(Type = "integer", not_null = true)
    public long totallength;
}

然后该实现查询的相关方法了;主要是根据字段类进行查询。
/**
* @author 徐晔
* @note 数据库操作方法的实现
*/
public class XYDBmanage {

public XYDBhelper dBhelper;
private SQLiteDatabase database;
private Context context;
private int version;
private String dbname;
private CursorFactory factory;

private static XYDBmanage xydBmanage = null;

public static XYDBmanage getInstance(Context context, String name,
        CursorFactory factory, int version) {
    if (xydBmanage == null) {
        synchronized (XYDBmanage.class) {
            if (xydBmanage == null) {
                xydBmanage = new XYDBmanage(context, name, factory, version);
            }
        }
    }
    return xydBmanage;
}

private XYDBmanage(Context context, String name, CursorFactory factory,
        int version) {
    this.context = context;
    this.version = version;
    this.dbname = name;
    this.factory = factory;
}

/**
 * 打开数据库
 */
private void openDB() {
    if (dBhelper == null) {
        dBhelper = new XYDBhelper(context, dbname, factory, version);
    }
    if (database == null) {
        database = dBhelper.getWritableDatabase();
    }
}

/**
 * 关闭数据库
 */
private void closeDB() {
    if (database.isOpen()) {
        database.close();
        database.releaseReference();
        database = null;
    }
}

/**
 * 根据Class获取表名字
 */
private String getTablename(Class<?> cls) {
    String tablename = "";
    XYTable mani = cls.getAnnotation(XYTable.class);
    if (mani == null) {
        return null;
    }
    tablename = mani.tablename();
    return tablename;
}

/**
 * 查询数据
 */
public synchronized List<?> getObjects(String columeName, String where,
        String order, Class<?> cls) throws Exception {
    String tablename = getTablename(cls);
    if (tablename == null || columeName == null) {
        return null;
    }
    List<Object> mList = new ArrayList<Object>();
    Object obj = null;
    StringBuilder mBuilder = new StringBuilder();
    mBuilder.append("select " + columeName + " from " + tablename);
    if (where != null) {
        mBuilder.append(" where " + where);
    }
    if (order != null) {
        mBuilder.append(" order by" + order);
    }
    openDB();
    Cursor mCursor = database.rawQuery(mBuilder.toString(), null);
    Field[] fields = cls.getFields();
    if (mCursor != null) {
        while (mCursor.moveToNext()) {
            obj = cls.newInstance();
            for (Field field : fields) {
                try {
                    setValue(obj, field, mCursor.getString(mCursor
                            .getColumnIndex(field.getName())));
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            mList.add(obj);
        }
    }
    if (!mCursor.isClosed()) {
        mCursor.close();
    }
    closeDB();
    return mList;
}

/**
 * 插入数据库
 */
public synchronized void insert(List<?> liss, Class<?> cls)
        throws Exception {
    ContentValues values = null;
    String tablename = getTablename(cls);
    openDB();
    for (Object temp : liss) {
        Field[] fields = cls.getFields();
        values = new ContentValues();
        for (Field field : fields) {
            if (temp.getClass().getField(field.getName()).get(temp) != null) {
                values.put(field.getName(),
                        temp.getClass().getField(field.getName()).get(temp)
                                .toString());
            }
        }
        Log.v("values", values + "");
        database.insert(tablename, null, values);
    }
    closeDB();
}

/**
 * 使用事物插入数据库
 */
public synchronized void insertwithTransaction(List<?> liss, Class<?> cls)
        throws Exception {

    ContentValues values = null;
    String tablename = getTablename(cls);
    openDB();
    database.beginTransaction();
    for (Object temp : liss) {
        Field[] fields = cls.getFields();
        values = new ContentValues();
        for (Field field : fields) {
            if (temp.getClass().getField(field.getName()).get(temp) != null) {
                values.put(field.getName(),
                        temp.getClass().getField(field.getName()).get(temp)
                                .toString());
            }
        }
        Log.v("values", values + "");
        database.insert(tablename, null, values);
    }
    database.setTransactionSuccessful();
    database.endTransaction();
    closeDB();
}

/**
 * 更新数据库
 */
public synchronized void updateState(Object obj, String where, Class<?> cls)
        throws Exception {
    StringBuilder SQL = new StringBuilder(" update ");
    StringBuilder value = new StringBuilder();
    String tablename = getTablename(cls);

    SQL.append(tablename);
    SQL.append(" set ");
    // 获得obj的所有属性
    Field[] fields = obj.getClass().getFields();
    for (Field field : fields) {
        // 如果属性的值不为空则存入values
        if (!field.getName().equals(tablename)) {
            if (null != field.get(obj)) {
                value.append(field.getName() + " = '"
                        + String.valueOf(field.get(obj) + "' ,"));
            }
        }
    }
    if (value.length() <= 0) {
        return;
    }
    value.delete(value.length() - 1, value.length());
    SQL.append(value);
    if (where != null && where.length() > 0) {
        SQL.append(" where " + where);
    }
    openDB();
    Log.v("updateState SQL=>", SQL.toString());
    database.execSQL(SQL.toString());
    clone();
}

/**
 * 删除数据库中指定的记录
 * 
 * @param listObj
 * @throws Exception
 */
public synchronized void delete(String where, Class<?> cls)
        throws Exception {
    String tablename = getTablename(cls);
    String sql = "delete from " + tablename;
    if (where != null && !where.equals("")) {
        sql = sql + " where " + where;
    }
    Log.v("sql=>", sql);
    openDB();
    database.execSQL(sql);
    closeDB();
}

/**
 * 执行自己的sql
 */
public synchronized void execSQL(String SQL) {
    // 获取数据库操作
    openDB();
    database = dBhelper.getWritableDatabase();
    database.execSQL(SQL);
    Log.v("sql=>", SQL);
    closeDB();
}

/**
 * 给obj对象的field属性赋值
 * 
 * @param obj
 *            对象
 * @param field
 *            属性
 * @param value
 *            值
 */
public void setValue(Object obj, Field field, String value) {
    try {
        // 获得field属性的类型名
        String class_type = field.getType().getName();
        // 将value转换成和属性类型一样的数据类型
        if (class_type.equals(String.class.getName())) {
            field.set(obj, value);
        } else if (class_type.equals("int")
                || class_type.equals(Integer.class.getName())) {
            field.set(obj, Integer.parseInt(value));
        } else if (class_type.equals("double")
                || class_type.equals(Double.class.getName())) {
            field.set(obj, Double.parseDouble(value));
        } else if (class_type.equals("boolean")
                || class_type.equals(Boolean.class.getName())) {
            field.set(obj, Boolean.parseBoolean(value));
        } else if (class_type.equals("float")
                || class_type.equals(Float.class.getName())) {
            field.set(obj, Float.parseFloat(value));
        } else if (class_type.equals("short")
                || class_type.equals(Short.class.getName())) {
            field.set(obj, Short.parseShort(value));
        } else if (class_type.equals("long")
                || class_type.equals(Long.class.getName())) {
            field.set(obj, Integer.parseInt(value));
        } else if (class_type.equals("char")
                || class_type.equals(Character.class.getName())) {
            field.set(obj, value);
        } else if (class_type.equals("byte")
                || class_type.equals(Byte.class.getName())) {
            field.set(obj, Byte.parseByte(value));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

,好了,大家按照这个思路完这些代码,后面使用数据库就会变得很简单。并且这一套实现思路不仅仅是只可以用反射实现,对于复杂的业务也支持自己写SQL语句来实现。不过要大家再次完美一下,实现相应的接口而已。抛砖引玉,希望大家指导。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值