做应用的大多离不开数据库的支持,但是就是这么常用的对象,你有没有想过让他更方便的使用呢?什么是更方便,我的定义就是不用在每次需要用它的时候对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) {// 如果属性的值不为空则存入valuesif (!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语句来实现。不过要大家再次完美一下,实现相应的接口而已。抛砖引玉,希望大家指导。

Android应用开发技巧之更方便的使用Sqlite相关推荐

  1. Android高效开发技巧:代码判空、逻辑判断语句

    文章目录 前言 一.判空 二.判断变量边界 1.if 2.while 3.for 总结 前言 在Android Studio中书写逻辑判断语句,如果一行一行自己进行书写,难免在速度上会落后别人,本文就 ...

  2. 从Android界面开发谈起(转)

    原文地址:http://blog.csdn.net/nieweilin/article/details/5967815 这篇文章没有打算有一个很好的逻辑去介绍android的某个方面,全盘大致上就是我 ...

  3. 从Android界面开发谈起

    这篇文章没有打算有一个很好的逻辑去介绍android的某个方面,全盘大致上就是我接触.了解android的ui开发后到现在的一些感想以及个人理解吧! 全文可能会涉及到java.android开发.an ...

  4. Android NFC 开发实例

    http://blog.csdn.net/pku_android/article/details/7430788 类: Android应用开发系列教程 Android应用开发技巧2012-04-06 ...

  5. Android JNI开发入门之二

    在上一篇文章<Android JNI开发入门之一>中,我介绍了Android应用程序(APK)怎样通过JNI调用Native C实现的共享库.本文将进一步介绍Android应用程序通过JN ...

  6. 一眼就看懂;Android App 开发前景介绍及学习路线规划

    Android App 开发的发展趋势和前景 安卓 App 开发是大趋势 从目前的各大社交终端以及移动媒体中手机占了百分之75.5的比例,随着各种移动端的系统升级,手机 App 也在现今这个社会面临着 ...

  7. 学Android移动开发 第1章 Android基础入门

    文章目录 1.1 Android简介 什么是Android Android和iOS主要区别 1.1.1 通信技术 1.1.2 Android起源 1.1.3 Android体系结构 1.1.4 Dal ...

  8. Android开发技巧——自定义控件之自定义属性

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

  9. 解密android日志xlog,安卓开发技巧2:自定义日志工具类XLog的实现

    安卓开发技巧二:自定义日志工具类XLog的实现 我们在开发过程中,打印日志是必不可少的一个调试环节,然而,直接使用系统自带的Log日志类,并不能满足我们实际项目的需求:假如我们现在在开发一款比较大的项 ...

最新文章

  1. 压缩人工智能的数据值
  2. Bicolor软件 中 GATB
  3. 没有任何基础的可以学python吗-对没有编程基础的人来说,直接学Python入门IT合适吗?...
  4. c++编辑器_盘点四款PDF编辑器,使用它们,编辑PDF文件没问题!
  5. QT的QBrush类的使用
  6. Surface Pro 4 和 Surface Book 使用名为 Surface UEFI(统一可扩展固件接口)的新固件接口...
  7. java修车_JAVA小练习34——使用java描述一个车类与一个修车厂类
  8. max 宏定义取消:error C2589: error C2059: 语法错误 : “::”
  9. 深度学习- 激活函数总结(Sigmoid, Tanh, Relu, leaky Relu, PReLU, Maxout, ELU, Softmax,交叉熵函数)
  10. oracle_jdbc新建实例,JDBC的操作步骤和实例
  11. 今天为你分享互联网营销的两个核心思维
  12. LOCK - 明确地锁定一个表
  13. oracle数据库赋权_Oracle角色权限创建用户赋权
  14. X Lossless Decoder for mac(XLD音频无损解码器)
  15. java applet怎么传参,使用不带浏览器的参数运行java applet
  16. 输入需求自动生成代码,这个AI有点厉害,可以替代真人吗?
  17. 提高睡眠质量的东西,每天晚上睡不着的你一定要试试
  18. odd在c语言中的意思,odd是什么意思
  19. 服务器打印后台程序没有响应,Win10提示打印后台处理程序服务没有运行如何解决...
  20. 万变不离其宗之反射原理篇

热门文章

  1. 交换机工作原理与配置小白看了都秒懂(配置华为交换机)
  2. 什么是段错误,段内,段间
  3. 微积分与最优化:最终解决方案的落地手段
  4. Qt 程序发布与运行(官方 windeployqt)
  5. 揭秘!不为人知的微商引流方法······
  6. QT 常用布局管理器
  7. 前馈神经网络_BP算法+R语言程序运行实例
  8. KB奇遇记(3):糟糕的IT现状
  9. 电脑文件夹无法重命名怎么办?
  10. 北京几点出门算错峰?哪些情况别开车?想要一路畅通,这些数据您得了解