Android数据库操作的简单封装

为什么要用ORM

在开发Android的过程中,我们基本上都会用到sqlite数据库,一般省事的情况下都是使用网上的一些orm框架操作sqlite数据库,比较有名的ORMLite、GreenDao和Active Android等。一般情况下,当预料到数据库会复杂到某个程度,就有必要引入数据库的ORM框架,这样可以大大降低开发和维护的成本。当然,站在巨人的肩膀上,选择好的开源库更可以事半功倍。
选择怎么样的ORM
Android上的ORM框架不少:GreenDao, Active Android,Schematic,Ollie,Sprinkles...到底应该如何选择?这些ORM框架用到的实现方式主要有几种:1.注解(运行时 Annotation,编译时 Annotation)2.反射3.直接生成代码这里简单地直接说结论:通过运行时注解或反射去建立数据表和实体的关系会导致性能比较低。从性能角度出发,应该选择使用编译时注解或代码生成的框架。当然,成熟程度,文档资料等也是考量点。

感兴趣的朋友可以自己去试试,今天我要说的是自己在android sdk 为我们提供的基础上进行自己的封装,达到方便高效的目的。

Android提供了一个SQLiteOpenHelper类来可以很方便的操作数据库,继承和扩展SQLiteOpenHelper类主要做的工作就是重写以下两个方法。
       onCreate: 当数据库被首次创建时执行该方法,一般将创建表等初始化操作在该方法中执行。
       onUpgrade:当打开数据库时传入的版本号与当前的版本号不同时会调用该方法。

想要封装自己的数据库操作类就要继承SQLiteOpenHelper,到达自己的目的了,首先看下我写的。

  1. public class DBHelper extends SQLiteOpenHelper{  
  2.     private static Logger logger = LoggerFactory.getLogger(DBHelper.class);  
  3.     private final static String DATABASE_PATH = Environment.getExternalStorageDirectory() + "/";  
  4.     private Context context;  
  5.     private int dbVersion;  
  6.   
  7.     public DBHelper(Context context, String dbName, int initVersion) {  
  8.         super(context, dbName, (SQLiteDatabase.CursorFactory)null, initVersion);  
  9.         this.context = context;  
  10.         this.dbVersion = initVersion;  
  11.     }  
  12.   
  13.     @Override  
  14.     public void onCreate(SQLiteDatabase db) {  
  15.         for(int i = 1; i <= this.dbVersion; ++i) {  
  16.             this.upgradeSqlData(db, i, false);  
  17.         }  
  18.     }  
  19.   
  20.     private void upgradeSqlData(SQLiteDatabase db, int version, boolean isDowngrade) {  
  21.         String fileName;  
  22.         if(isDowngrade) {  
  23.             fileName = "_" + version + "_db.sql";  
  24.         } else {  
  25.             fileName = version + "_db.sql";  
  26.         }  
  27.   
  28.         BufferedReader bufferedReader = null;  
  29.         db.beginTransaction();  
  30.   
  31.         try {  
  32.             InputStream e = this.context.getAssets().open(fileName);  
  33.             InputStreamReader reader = new InputStreamReader(e, "UTF-8");  
  34.             bufferedReader = new BufferedReader(reader);  
  35.             String line = bufferedReader.readLine();  
  36.             StringBuilder sb = new StringBuilder();  
  37.   
  38.             while(true) {  
  39.                 while(line != null) {  
  40.                     line = line.trim();  
  41.                     if(!"".equals(line) && line.charAt(0) != 47 && line.charAt(0) != 45) {  
  42.                         boolean middleIndex = true;  
  43.                         int middleIndex1;  
  44.                         if((middleIndex1 = line.lastIndexOf("--")) != -1) {  
  45.                             line = line.substring(0, middleIndex1);  
  46.                         }  
  47.   
  48.                         sb.append(line);  
  49.                         String sql = sb.toString();  
  50.                         if(!"".equals(sql) && sql.charAt(sql.length() - 1) == 59) {  
  51.                             logger.debug("load sql:{}", sql);  
  52.                             db.execSQL(sql.substring(0, sql.indexOf(59)));  
  53.                             sb = new StringBuilder();  
  54.                         }  
  55.   
  56.                         line = bufferedReader.readLine();  
  57.                     } else {  
  58.                         line = bufferedReader.readLine();  
  59.                     }  
  60.                 }  
  61.   
  62.                 db.setTransactionSuccessful();  
  63.                 logger.info("load file {} success.", fileName);  
  64.                 Log.e("TAG","load file {} success." + fileName);  
  65.                 break;  
  66.             }  
  67.         } catch (Exception var20) {  
  68.             logger.error("load file {} failed.", fileName, var20);  
  69.             Log.e("TAG","load file {} success." + fileName);  
  70.         } finally {  
  71.             try {  
  72.                 if(bufferedReader != null) {  
  73.                     bufferedReader.close();  
  74.                 }  
  75.   
  76.                 db.endTransaction();  
  77.             } catch (IOException var19) {  
  78.                 ;  
  79.             }  
  80.   
  81.         }  
  82.   
  83.     }  
  84.   
  85.     @Override  
  86.     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  87.         for(int i = oldVersion + 1; i <= newVersion; ++i) {  
  88.             this.upgradeSqlData(db, i, false);  
  89.         }  
  90.     }  
  91.   
  92.     public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {  
  93.         for(int i = oldVersion - 1; i >= newVersion; --i) {  
  94.             this.upgradeSqlData(db, i, false);  
  95.         }  
  96.   
  97.     }  
  98.   
  99. //    @Override  
  100. //    public SQLiteDatabase getWritableDatabase() {  
  101. //        File file = new File(DATABASE_PATH + "dbtest");  
  102. //        if (!file.exists()) {  
  103. //            file.mkdirs();  
  104. //  
  105. //        }  
  106. //        File dbFile = new File(file,"mydb.db");  
  107. //        if (!dbFile.exists())  
  108. //            try {  
  109. //                dbFile.createNewFile();  
  110. //            } catch (IOException e) {  
  111. //                e.printStackTrace();  
  112. //            }  
  113. //        return SQLiteDatabase.openOrCreateDatabase(dbFile,null);  
  114. //    }  
  115. //  
  116. //    @Override  
  117. //    public SQLiteDatabase getReadableDatabase() {  
  118. //        return getWritableDatabase();  
  119. //    }  
  120. }  

重写了oncreate()方法和onUpgrade()方法,前面也说了两个方法的用途,数据库初次创建的时候,肯定是要建数据库建表,所以在onCreate()的方法执行了创建表的sql语句,
因为默认了数据库的创建路径,所以我们是不需要手动的创建数据库文件的,如果你想制定数据库创建的路径,那么就得自己创建数据库文件了,类中注释掉的代码就是指定在sdcard中创建数据库文件的代码。再说一说sql建表语句,我将建表的sql语句写到了android目录下的assets文件夹下面,在该文件夹下新建一个文本文件,后缀改为.sql其它格式也行,但是要注意自己代码中要一致。
  1. -- Describe USER  
  2. CREATE TABLE cdd_user (  
  3.   id        INTEGER PRIMARY KEY AUTOINCREMENT,  
  4.   user_name        TEXT,         --对应userCode  
  5.   user_age       TEXT         --对应userName  
  6. );  
这里要说明一下,这个.sql文件的命名是要有一定规则的,以数字开头然后下划线然后加上db,如 1_db.sql 当然这只是我自己定义的规则方便读取,你们也可以定义自己的规则,但是DBHelper中的方法就得自己修改了,不然是找不到文件的。1_db.sql的1代表了当前的数据库版本号是1,每次相对于上个版本增加了表就新增加一个sql文件,命名前的数字比上次的sql文件加1,这样数据库就能自动创建表新增表了,而不需要我们删除app再安装,这就是数据库版本号的用处。
下面就说说数据库dao,android sdk已经封装好了插入,删除,更新,查询方法,但是这样每次都写一大堆东西太冗余了,我们简单的封装一下就好多了,首先写个基类其中包含增删改查。

  1. public class BaseRepository<T> {  
  2.     protected Logger logger = LoggerFactory.getLogger(this.getClass());  
  3.     protected DBHelper dbHelper;  
  4.   
  5.     public BaseRepository(Context context) {  
  6.         dbHelper = DBUtil.getInstance(context).getDbHelper();  
  7.     }  
  8.   
  9.     /** 
  10.      * 数据插入 
  11.      * @param table 
  12.      * @param nullColumnHack 
  13.      * @param values 
  14.      * @return 
  15.      */  
  16.     public long insert(String table, String nullColumnHack, ContentValues values) {  
  17.         long ret = 0;  
  18.         SQLiteDatabase database = dbHelper.getWritableDatabase();  
  19.         database.beginTransaction();  
  20.         try {  
  21.             ret = database.insert(table, nullColumnHack, values);  
  22.             database.setTransactionSuccessful();  
  23.         } catch (RuntimeException e) {  
  24.             logger.error("insert error. ", e);  
  25.         } finally {  
  26.             database.endTransaction();  
  27.         }  
  28.         return ret;  
  29.     }  
  30.   
  31.     /** 
  32.      * 数据查询 
  33.      * @param table 
  34.      * @param columns 
  35.      * @param selection 
  36.      * @param selectionArgs 
  37.      * @param groupBy 
  38.      * @param having 
  39.      * @param orderBy 
  40.      * @param limit 
  41.      * @param <T> 
  42.      * @return 
  43.      */  
  44.     public <T> List<T> query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, Integer limit) {  
  45.         List<T> results = new ArrayList<T>();  
  46.         Cursor cursor = null;  
  47.         try {  
  48.             if (limit != null) {  
  49.                 cursor = dbHelper.getReadableDatabase().query(table, columns, selection, selectionArgs, groupBy, having, orderBy, limit + "");  
  50.             } else {  
  51.                 cursor = dbHelper.getReadableDatabase().query(table, columns, selection, selectionArgs, groupBy, having, orderBy);  
  52.             }  
  53.             results = queryResult(cursor);  
  54.         } catch (RuntimeException e) {  
  55.             logger.error("query error. ", e);  
  56.         } finally {  
  57.             if (cursor != null) {  
  58.                 cursor.close();  
  59.             }  
  60.         }  
  61.         return results;  
  62.     }  
  63.   
  64.     /** 
  65.      * 转换为对象 
  66.      * @param cursor 
  67.      * @param <T> 
  68.      * @return 
  69.      */  
  70.     public <T> List<T> queryResult(Cursor cursor) {  
  71.         throw new RuntimeException("Please overwrite method.");  
  72.     }  
  73.   
  74.     /** 
  75.      * 数据更新 
  76.      * @param table 
  77.      * @param values 
  78.      * @param whereClause 
  79.      * @param whereArgs 
  80.      * @return 
  81.      */  
  82.     public int update(String table, ContentValues values, String whereClause, String[] whereArgs) {  
  83.         int ret = 0;  
  84.         SQLiteDatabase database = dbHelper.getWritableDatabase();  
  85.         database.beginTransaction();  
  86.         try {  
  87.             ret = database.update(table, values, whereClause, whereArgs);  
  88.             database.setTransactionSuccessful();  
  89.         } catch (RuntimeException e) {  
  90.             logger.error("update error. ", e);  
  91.         } finally {  
  92.             database.endTransaction();  
  93.         }  
  94.         return ret;  
  95.     }  
  96.   
  97.     /** 
  98.      * 数据删除 
  99.      * @param table 
  100.      * @param whereClause 
  101.      * @param whereArgs 
  102.      * @return 
  103.      */  
  104.     public int delete(String table, String whereClause, String[] whereArgs) {  
  105.   
  106.         int ret = 0;  
  107.         SQLiteDatabase database = dbHelper.getWritableDatabase();  
  108.         database.beginTransaction();  
  109.         try {  
  110.             ret = database.delete(table, whereClause, whereArgs);  
  111.             database.setTransactionSuccessful();  
  112.         } catch (RuntimeException e) {  
  113.             logger.error("delete error. ", e);  
  114.         } finally {  
  115.             database.endTransaction();  
  116.         }  
  117.         return ret;  
  118.     }  
  119.   
  120. }  

后面所有的dao都继承该基类,传入泛型就得到了我们想要的,下面给个User的dao例子

  1. public class UserRepository extends BaseRepository<User>{  
  2.   
  3.     public UserRepository(Context context) {  
  4.         super(context);  
  5.     }  
  6.   
  7.     /** 
  8.      * 插入数据 
  9.      * @param user 
  10.      * @return 
  11.      */  
  12.     public long insert(User user) {  
  13.         ContentValues values = getContentValues(user);  
  14.         values.remove("id");  
  15.         return insert(DBConstant.TABLE_USER,null,values);  
  16.     }  
  17.   
  18.     /** 
  19.      * 更新数据 
  20.      * @param user 
  21.      */  
  22.     public void update(User user) {  
  23.         ContentValues cv = getContentValues(user);  
  24.         cv.remove("id");  
  25.         update(DBConstant.TABLE_USER,cv,"id = ?",new String[]{user.getId()+""});  
  26.     }  
  27.   
  28.     /** 
  29.      * 删除数据 
  30.      * @param id 
  31.      */  
  32.     public void delete(int id) {  
  33.         delete(DBConstant.TABLE_USER,"id = ?",new String[]{id+""});  
  34.     }  
  35.   
  36.     /** 
  37.      * 查询所有数据 
  38.      * @return 
  39.      */  
  40.     public List<User> readAllUsers() {  
  41.         List<User> list = query(DBConstant.TABLE_USER,null,nullnullnullnullnull,null);  
  42.         if(list != null && !list.isEmpty())  
  43.         {  
  44.             return list;  
  45.         }  
  46.         return null;  
  47.     }  
  48.   
  49.     @Override  
  50.     public  List<User> queryResult(Cursor cursor) {  
  51.         List<User> userList = new ArrayList<User>();  
  52.         User user;  
  53.         while (cursor.moveToNext()) {  
  54.             user = new User();  
  55.             user.setId(cursor.getInt(cursor.getColumnIndex("id")));  
  56.             user.setUserName(cursor.getString(cursor.getColumnIndex("user_name")));  
  57.             user.setAge(cursor.getInt(cursor.getColumnIndex("user_age")));  
  58.             userList.add(user);  
  59.         }  
  60.         return userList;  
  61.     }  
  62.   
  63.     private ContentValues getContentValues(User user) {  
  64.         ContentValues cv = new ContentValues();  
  65.         cv.put("id",user.getId());  
  66.         cv.put("user_name",user.getUserName());  
  67.         cv.put("user_age",user.getAge());  
  68.         return cv;  
  69.     }  
嗯,看上去简单清爽了很多,需要重写的代码也没有几个,主要还是bean和cursor的转换,对数据库不太了解的朋友可以去查查相关的资料,这里就不做基本知识的普及了。

最后将DBHelper做成单例模式,也贴下代码

  1. public class DBUtil {  
  2.     private static DBUtil instance;  
  3.     private static DBHelper dbHelper;  
  4.     private DBUtil() {  
  5.     }  
  6.   
  7.     public static DBUtil getInstance(Context context) {  
  8.         if (instance == null) {  
  9.             instance = new DBUtil();  
  10.             initDBHelper(context);  
  11.         }  
  12.         return instance;  
  13.     }  
  14.   
  15.     private static void initDBHelper(Context context) {  
  16.         dbHelper = new DBHelper(context, DBConstant.DB_NAME,DBConstant.DB_INIT_VERSION);  
  17.         dbHelper.onCreate(dbHelper.getWritableDatabase());  
  18.     }  
  19.   
  20.   
  21.     public DBHelper getDbHelper(){  
  22.         return dbHelper;  
  23.     }  

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值