2012年4月15日星期日

Android sqlite数据库操作通用框架AHibernate(二)源码

Android sqlite数据库操作通用框架AHibernate(二)源码



贴出源代码供大家交流使用,欢迎朋友们对代码提供宝贵意见,直接写到评论中即可.使用示例和步骤见上一篇博客:http://blog.csdn.net/lk_blog/article/details/7455992源码和示例下载地址: http://download.csdn.net/detail/lk_blog/4222048(一)注解类:Table.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.annotation;    import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;    @Retention(RetentionPolicy.RUNTIME)  @Target( { java.lang.annotation.ElementType.TYPE })  public @interface Table {      /**      * 表名      *       * @return      */      public abstract String name();  }</span>  Column.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.annotation;    import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;    @Retention(RetentionPolicy.RUNTIME)  @Target( { java.lang.annotation.ElementType.FIELD })  public @interface Column {      /**      * 列名      *       * @return      */      public abstract String name();        public abstract String type() default "";        public abstract int length() default 0;  }</span>  Id.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.annotation;    import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;    @Retention(RetentionPolicy.RUNTIME)  @Target( { java.lang.annotation.ElementType.FIELD })  public @interface Id {  }</span>  (二)Util类:TableHelper.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.util;    import android.database.sqlite.SQLiteDatabase;  import android.util.Log;    import java.lang.reflect.Field;  import java.sql.Blob;  import java.util.ArrayList;  import java.util.LinkedHashMap;  import java.util.List;  import java.util.Map;    import com.tgb.lk.ahibernate.annotation.Column;  import com.tgb.lk.ahibernate.annotation.Id;  import com.tgb.lk.ahibernate.annotation.Table;    public class TableHelper {      private static final String TAG = "AHibernate";        public static <T> void createTablesByClasses(SQLiteDatabase db,              Class<?>[] clazzs) {          for (Class<?> clazz : clazzs)              createTable(db, clazz);      }        public static <T> void dropTablesByClasses(SQLiteDatabase db,              Class<?>[] clazzs) {          for (Class<?> clazz : clazzs)              dropTable(db, clazz);      }        public static <T> void createTable(SQLiteDatabase db, Class<T> clazz) {          String tableName = "";          if (clazz.isAnnotationPresent(Table.class)) {              Table table = (Table) clazz.getAnnotation(Table.class);              tableName = table.name();          }            StringBuilder sb = new StringBuilder();          sb.append("CREATE TABLE ").append(tableName).append(" (");            List<Field> allFields = TableHelper                  .joinFields(clazz.getDeclaredFields(), clazz.getSuperclass()                          .getDeclaredFields());          for (Field field : allFields) {              if (!field.isAnnotationPresent(Column.class)) {                  continue;              }                Column column = (Column) field.getAnnotation(Column.class);                String columnType = "";              if (column.type().equals(""))                  columnType = getColumnType(field.getType());              else {                  columnType = column.type();              }                sb.append(column.name() + " " + columnType);                if (column.length() != 0) {                  sb.append("(" + column.length() + ")");              }                if (((field.isAnnotationPresent(Id.class)) && (field.getType() == Integer.TYPE))                      || (field.getType() == Integer.class))                  sb.append(" primary key autoincrement");              else if (field.isAnnotationPresent(Id.class)) {                  sb.append(" primary key");              }                sb.append(", ");          }            sb.delete(sb.length() - 2, sb.length() - 1);          sb.append(")");            String sql = sb.toString();            Log.d(TAG, "crate table [" + tableName + "]: " + sql);            db.execSQL(sql);      }        public static <T> void dropTable(SQLiteDatabase db, Class<T> clazz) {          String tableName = "";          if (clazz.isAnnotationPresent(Table.class)) {              Table table = (Table) clazz.getAnnotation(Table.class);              tableName = table.name();          }          String sql = "DROP TABLE IF EXISTS " + tableName;          Log.d(TAG, "dropTable[" + tableName + "]:" + sql);          db.execSQL(sql);      }        private static String getColumnType(Class<?> fieldType) {          if (String.class == fieldType) {              return "TEXT";          }          if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {              return "INTEGER";          }          if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {              return "BIGINT";          }          if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {              return "FLOAT";          }          if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {              return "INT";          }          if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {              return "DOUBLE";          }          if (Blob.class == fieldType) {              return "BLOB";          }            return "TEXT";      }        // 合并Field数组并去重,并实现过滤掉非Column字段,和实现Id放在首字段位置功能      public static List<Field> joinFields(Field[] fields1, Field[] fields2) {          Map<String, Field> map = new LinkedHashMap<String, Field>();          for (Field field : fields1) {              // 过滤掉非Column定义的字段              if (!field.isAnnotationPresent(Column.class)) {                  continue;              }              Column column = (Column) field.getAnnotation(Column.class);              map.put(column.name(), field);          }          for (Field field : fields2) {              // 过滤掉非Column定义的字段              if (!field.isAnnotationPresent(Column.class)) {                  continue;              }              Column column = (Column) field.getAnnotation(Column.class);              if (!map.containsKey(column.name())) {                  map.put(column.name(), field);              }          }          List<Field> list = new ArrayList<Field>();          for (String key : map.keySet()) {              Field tempField = map.get(key);              // 如果是Id则放在首位置.              if (tempField.isAnnotationPresent(Id.class)) {                  list.add(0, tempField);              } else {                  list.add(tempField);              }          }          return list;      }  }</span>  MyDBHelper.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.util;    import android.content.Context;  import android.database.sqlite.SQLiteDatabase;  import android.database.sqlite.SQLiteOpenHelper;    public class MyDBHelper extends SQLiteOpenHelper {      private Class<?>[] modelClasses;        public MyDBHelper(Context context, String databaseName,              SQLiteDatabase.CursorFactory factory, int databaseVersion,              Class<?>[] modelClasses) {          super(context, databaseName, factory, databaseVersion);          this.modelClasses = modelClasses;      }        public void onCreate(SQLiteDatabase db) {          TableHelper.createTablesByClasses(db, this.modelClasses);      }        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {          TableHelper.dropTablesByClasses(db, this.modelClasses);          onCreate(db);      }  }</span>  (三)接口和实现:BaseDao.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.dao;    import java.util.List;  import java.util.Map;    import android.database.sqlite.SQLiteOpenHelper;    public interface BaseDao<T> {        public SQLiteOpenHelper getDbHelper();            public abstract long insert(T entity);            public abstract void delete(int id);            public abstract void delete(Integer... ids);        public abstract void update(T entity);        public abstract T get(int id);        public abstract List<T> rawQuery(String sql, String[] selectionArgs);        public abstract List<T> find();        public abstract List<T> find(String[] columns, String selection,              String[] selectionArgs, String groupBy, String having,              String orderBy, String limit);        public abstract boolean isExist(String sql, String[] selectionArgs);        /**      * 将查询的结果保存为名值对map.      *       * @param sql      *            查询sql      * @param selectionArgs      *            参数值      * @return 返回的Map中的key全部是小写形式.      */      public List<Map<String, String>> query2MapList(String sql,              String[] selectionArgs);            /**      * 封装执行sql代码.      * @param sql      * @param selectionArgs      */      public void execSql(String sql, Object[] selectionArgs);    }</span>  BaseDaoImpl.java[java] view plaincopy<span >package com.tgb.lk.ahibernate.dao.impl;    import android.content.ContentValues;  import android.database.Cursor;  import android.database.sqlite.SQLiteDatabase;  import android.database.sqlite.SQLiteOpenHelper;  import android.util.Log;  import java.lang.reflect.Field;  import java.sql.Blob;  import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;  import java.util.Map;    import com.tgb.lk.ahibernate.annotation.Column;  import com.tgb.lk.ahibernate.annotation.Id;  import com.tgb.lk.ahibernate.annotation.Table;  import com.tgb.lk.ahibernate.dao.BaseDao;  import com.tgb.lk.ahibernate.util.TableHelper;    /**  * AHibernate概要 <br/>  * (一)支持功能: 1.自动建表,支持属性来自继承类:可根据注解自动完成建表,并且对于继承类中的注解字段也支持自动建表. 2.自动支持增删改  * ,增改支持对象化操作:增删改是数据库操作的最基本单元,不用重复写这些增删改的代码,并且添加和更新支持类似于hibernate中的对象化操作.  * 3.查询方式灵活:支持android框架提供的方式,也支持原生sql方式.  * 4.查询结果对象化:对于查询结果可自动包装为实体对象,类似于hibernate框架.  * 5.查询结果灵活:查询结果支持对象化,也支持结果为List<Map<String,String>>形式,这个方法在实际项目中很实用,且效率更好些.  * 6.日志较详细:因为android开发不支持热部署调试,运行报错时可根据日志来定位错误,这样可以减少运行Android的次数. <br/>  * (二)不足之处: <br/>  * 1.id暂时只支持int类型,不支持uuid,在sqlite中不建议用uuid.  * 2.现在每个方法都自己开启和关闭事务,暂时还不支持在一个事务中做多个操作然后统一提交事务. <br/>  * (三)作者寄语:<br/>  * 昔日有JavaScript借Java发展,今日也希望AHibernate借Hibernate之名发展.  * 希望这个项目以后会成为开源社区的重要一员,更希望这个项目能给所有Android开发者带便利.  * 欢迎访问我的博客:http://blog.csdn.net/lk_blog,  * 这里有这个框架的使用范例和源码,希望朋友们多多交流完善这个框架,共同推动中国开源事业的发展,AHibernate期待与您共创美好未来!!!  */  public class BaseDaoImpl<T> implements BaseDao<T> {      private String TAG = "AHibernate";      private SQLiteOpenHelper dbHelper;      private String tableName;      private String idColumn;      private Class<T> clazz;      private List<Field> allFields;        public BaseDaoImpl(SQLiteOpenHelper dbHelper) {          this.dbHelper = dbHelper;            this.clazz = ((Class<T>) ((java.lang.reflect.ParameterizedType) super                  .getClass().getGenericSuperclass()).getActualTypeArguments()[0]);            if (this.clazz.isAnnotationPresent(Table.class)) {              Table table = (Table) this.clazz.getAnnotation(Table.class);              this.tableName = table.name();          }            // 加载所有字段          this.allFields = TableHelper.joinFields(this.clazz.getDeclaredFields(),                  this.clazz.getSuperclass().getDeclaredFields());            // 找到主键          for (Field field : this.allFields) {              if (field.isAnnotationPresent(Id.class)) {                  Column column = (Column) field.getAnnotation(Column.class);                  this.idColumn = column.name();                  break;              }          }            Log.d(TAG, "clazz:" + this.clazz + " tableName:" + this.tableName                  + " idColumn:" + this.idColumn);      }        public SQLiteOpenHelper getDbHelper() {          return dbHelper;      }        public T get(int id) {          String selection = this.idColumn + " = ?";          String[] selectionArgs = { Integer.toString(id) };          Log.d(TAG, "[get]: select * from " + this.tableName + " where "                  + this.idColumn + " = '" + id + "'");          List<T> list = find(null, selection, selectionArgs, null, null, null,                  null);          if ((list != null) && (list.size() > 0)) {              return (T) list.get(0);          }          return null;      }        public List<T> rawQuery(String sql, String[] selectionArgs) {          Log.d(TAG, "[rawQuery]: " + sql);            List<T> list = new ArrayList<T>();          SQLiteDatabase db = null;          Cursor cursor = null;          try {              db = this.dbHelper.getReadableDatabase();              cursor = db.rawQuery(sql, selectionArgs);                getListFromCursor(list, cursor);          } catch (Exception e) {              Log.e(this.TAG, "[rawQuery] from DB Exception.");              e.printStackTrace();          } finally {              if (cursor != null) {                  cursor.close();              }              if (db != null) {                  db.close();              }          }            return list;      }        public boolean isExist(String sql, String[] selectionArgs) {          Log.d(TAG, "[isExist]: " + sql);            SQLiteDatabase db = null;          Cursor cursor = null;          try {              db = this.dbHelper.getReadableDatabase();              cursor = db.rawQuery(sql, selectionArgs);              if (cursor.getCount() > 0) {                  return true;              }          } catch (Exception e) {              Log.e(this.TAG, "[isExist] from DB Exception.");              e.printStackTrace();          } finally {              if (cursor != null) {                  cursor.close();              }              if (db != null) {                  db.close();              }          }          return false;      }        public List<T> find() {          return find(null, null, null, null, null, null, null);      }        public List<T> find(String[] columns, String selection,              String[] selectionArgs, String groupBy, String having,              String orderBy, String limit) {          Log.d(TAG, "[find]");            List<T> list = new ArrayList<T>();          SQLiteDatabase db = null;          Cursor cursor = null;          try {              db = this.dbHelper.getReadableDatabase();              cursor = db.query(this.tableName, columns, selection,                      selectionArgs, groupBy, having, orderBy, limit);                getListFromCursor(list, cursor);          } catch (Exception e) {              Log.e(this.TAG, "[find] from DB Exception");              e.printStackTrace();          } finally {              if (cursor != null) {                  cursor.close();              }              if (db != null) {                  db.close();              }          }            return list;      }        private void getListFromCursor(List<T> list, Cursor cursor)              throws IllegalAccessException, InstantiationException {          while (cursor.moveToNext()) {              T entity = this.clazz.newInstance();                for (Field field : this.allFields) {                  Column column = null;                  if (field.isAnnotationPresent(Column.class)) {                      column = (Column) field.getAnnotation(Column.class);                        field.setAccessible(true);                      Class<?> fieldType = field.getType();                        int c = cursor.getColumnIndex(column.name());                      if (c < 0) {                          continue; // 如果不存则循环下个属性值                      } else if ((Integer.TYPE == fieldType)                              || (Integer.class == fieldType)) {                          field.set(entity, cursor.getInt(c));                      } else if (String.class == fieldType) {                          field.set(entity, cursor.getString(c));                      } else if ((Long.TYPE == fieldType)                              || (Long.class == fieldType)) {                          field.set(entity, Long.valueOf(cursor.getLong(c)));                      } else if ((Float.TYPE == fieldType)                              || (Float.class == fieldType)) {                          field.set(entity, Float.valueOf(cursor.getFloat(c)));                      } else if ((Short.TYPE == fieldType)                              || (Short.class == fieldType)) {                          field.set(entity, Short.valueOf(cursor.getShort(c)));                      } else if ((Double.TYPE == fieldType)                              || (Double.class == fieldType)) {                          field.set(entity, Double.valueOf(cursor.getDouble(c)));                      } else if (Blob.class == fieldType) {                          field.set(entity, cursor.getBlob(c));                      } else if (Character.TYPE == fieldType) {                          String fieldValue = cursor.getString(c);                            if ((fieldValue != null) && (fieldValue.length() > 0)) {                              field.set(entity, Character.valueOf(fieldValue                                      .charAt(0)));                          }                      }                  }              }                list.add((T) entity);          }      }        public long insert(T entity) {          Log.d(TAG, "[insert]: inset into " + this.tableName + " "                  + entity.toString());          SQLiteDatabase db = null;          try {              db = this.dbHelper.getWritableDatabase();              ContentValues cv = new ContentValues();              setContentValues(entity, cv, "create");              long row = db.insert(this.tableName, null, cv);              return row;          } catch (Exception e) {              Log.d(this.TAG, "[insert] into DB Exception.");              e.printStackTrace();          } finally {              if (db != null) {                  db.close();              }          }            return 0L;      }        public void delete(int id) {          SQLiteDatabase db = this.dbHelper.getWritableDatabase();          String where = this.idColumn + " = ?";          String[] whereValue = { Integer.toString(id) };            Log.d(TAG, "[delete]: delelte from " + this.tableName + " where "                  + where.replace("?", String.valueOf(id)));            db.delete(this.tableName, where, whereValue);          db.close();      }        public void delete(Integer... ids) {          if (ids.length > 0) {              StringBuffer sb = new StringBuffer();              for (int i = 0; i < ids.length; i++) {                  sb.append('?').append(',');              }              sb.deleteCharAt(sb.length() - 1);              SQLiteDatabase db = this.dbHelper.getWritableDatabase();              String sql = "delete from " + this.tableName + " where "                      + this.idColumn + " in (" + sb + ")";                Log.d(TAG, "[delete]: " + sql);                db.execSQL(sql, (Object[]) ids);              db.close();          }      }        public void update(T entity) {          SQLiteDatabase db = null;          try {              db = this.dbHelper.getWritableDatabase();              ContentValues cv = new ContentValues();                setContentValues(entity, cv, "update");                String where = this.idColumn + " = ?";              int id = Integer.parseInt(cv.get(this.idColumn).toString());              cv.remove(this.idColumn);                Log.d(TAG, "[update]: update " + this.tableName + " where "                      + where.replace("?", String.valueOf(id)));                String[] whereValue = { Integer.toString(id) };              db.update(this.tableName, cv, where, whereValue);          } catch (Exception e) {              Log.d(this.TAG, "[update] DB Exception.");              e.printStackTrace();          } finally {              if (db != null)                  db.close();          }      }        private void setContentValues(T entity, ContentValues cv, String type)              throws IllegalAccessException {            for (Field field : this.allFields) {              if (!field.isAnnotationPresent(Column.class)) {                  continue;              }              Column column = (Column) field.getAnnotation(Column.class);                field.setAccessible(true);              Object fieldValue = field.get(entity);              if (fieldValue == null)                  continue;              if (("create".equals(type))                      && (field.isAnnotationPresent(Id.class))) {                  continue;              }              cv.put(column.name(), fieldValue.toString());          }      }        /**      * 将查询的结果保存为名值对map.      *       * @param sql      *            查询sql      * @param selectionArgs      *            参数值      * @return 返回的Map中的key全部是小写形式.      */      public List<Map<String, String>> query2MapList(String sql,              String[] selectionArgs) {          Log.d(TAG, "[query2MapList]: " + sql);          SQLiteDatabase db = null;          Cursor cursor = null;          List<Map<String, String>> retList = new ArrayList<Map<String, String>>();          try {              db = this.dbHelper.getReadableDatabase();              cursor = db.rawQuery(sql, selectionArgs);              while (cursor.moveToNext()) {                  Map<String, String> map = new HashMap<String, String>();                  for (String columnName : cursor.getColumnNames()) {                      map.put(columnName.toLowerCase(), cursor.getString(cursor                              .getColumnIndex(columnName)));                  }                  retList.add(map);              }          } catch (Exception e) {              Log.e(TAG, "[query2MapList] from DB exception");              e.printStackTrace();          } finally {              if (cursor != null) {                  cursor.close();              }              if (db != null) {                  db.close();              }          }            return retList;      }        /**      * 封装执行sql代码.      *       * @param sql      * @param selectionArgs      */      public void execSql(String sql, Object[] selectionArgs) {          SQLiteDatabase db = null;          Log.d(TAG, "[execSql]: " + sql);          try {              db = this.dbHelper.getWritableDatabase();              if (selectionArgs == null) {                  db.execSQL(sql);              } else {                  db.execSQL(sql, selectionArgs);              }          } catch (Exception e) {              Log.e(TAG, "[execSql] DB exception.");              e.printStackTrace();          } finally {              if (db != null) {                  db.close();              }          }      }  }</span>  


TAG:phone 开发