greendao的使用

以前开发用到数据库时,基本上都是用android原生的sql语句,写那些语句时稍有不慎,就给你抛出一个exception。现在网上有很多的数据库ORM框架,今天写篇文章来记录一下比较好用的框架:greendao的使用。关于greendao的介绍,网上已经有很多了,可以自行查阅。


准备工作

  • 1、新建一个android工程,在main目录下新建一个文件夹java-gen,如下图:
  • 2、在同一个project下,再新建一个java module,并新创建一个类,如下图:
  • 3、在android module中的build.gradle文件中加上以下代码:

    sourceSets {    
          main {        
                    java.srcDirs = ['src/main/java',  'src/main/java-gen']    
          }
    }
    
    compile 'de.greenrobot:greendao:2.1.0'
    

在java module中的build.grade文件中添加以下代码:

  compile 'de.greenrobot:greendao-generator:2.1.0'

自动生成数据库Bean和Dao类

以下是java module中类的实现

  public class GreenDaoGeneratorTest {
      //自动生成类的包名  
      public static String PACKAGE_NAME = "com.blainpeng.greendao"; 
      //这里的OUT_DIR就是我们新建的java-gem的路径     
      public static String OUT_DIR = "/Users/Desktop/AndroidProject/GreenDaoDemo/app/src/main/java-gen";    
      public static void main(String[] args) throws Exception {        
      // 1、创建一个用于添加实体(entity)的模式(Schema)对象      
      Schema schema = new Schema(1, PACKAGE_NAME); //第一个参数为数据库的版本号 
       // Schema schema = new Schema(2, PACKAGE_NAME);版本号升级
      // 2、获得了Schema对象后就可以添加实体了,也就是添加数据库表了。   
        addCustomer(schema);      
      // 3、利用DaoGenerator类生成代码,并将自动生成的代码放到指定的目录       
        new DaoGenerator().generateAll(schema, OUT_DIR);    
      }
        
      private static void addCustomer(Schema schema) {
      // 4、一个实体类就关联到数据库中的一张表,此处表名为:Customer         
        Entity entity = schema.addEntity("Customer");         
      // 5、设置数据库表中的字段(greenDao会自动根据实体类的属性来创建表字段,并赋予默认值)       
        entity.addIdProperty().autoincrement();            
        entity.addStringProperty("name").notNull();            
        entity.addStringProperty("age").notNull();        
        entity.addStringProperty("phone").notNull();        
        entity.addStringProperty("marriage").notNull();          
        //entity.addStringProperty("address");  升级时添加的新列名  
      }
}

写好这个类以后,点击它,右击run ,出现下图说明运行成功:


此时,java-gen文件夹里面就有4个类了。


如何调用?

  • 创建一个类继承自Application,上代码:

      public class BaseApplication extends Application {    
          public static DaoMaster                daoMaster;    
          public static DaoSession               daoSession;   
          public static SQLiteDatabase           db;    
          public static DaoMaster.DevOpenHelper  helper;    
          @Override    
          public void onCreate()    {        
              super.onCreate();     
         /*       
          * 通过 DaoMaster 的内部类 DevOpenHelper,你可以得到一个便利的 
            SQLiteOpenHelper 对象       
          */        
        helper = new DaoMaster.DevOpenHelper(this, "dbname.db", null);        
        db = helper.getWritableDatabase();        
        daoMaster = new DaoMaster(db);        
        daoSession = daoMaster.newSession();       
        }    
        public static DaoSession getDaoSession()    {        
            return daoSession;    
        }    
        public static SQLiteDatabase getSqLiteDatabase()    {        
            return db;    
        }
    }
    
  • 在activity中调用

    //先获得dao的实例
    customerDao = BaseApplication.getDaoSession().getCustomerDao();
    //创建对象,并将对象添加到数据库
    Customer customer = new Customer(null, name, age, phone,marriage);
    customerDao.insert(customer);
    
    //查询方法
    list = customerDao.loadAll();
    

使用greendao,对于数据库的CRUD,我们只需要往里面添加一个对象就可以了,再也不需要去记那些spl语句子,是不是非常爽啊。


如何安全地升级数据库?

  • 数据库升级的原理
    先创建一个新表,将原表中的数据进行复制,再把原数据库表删掉

      // 删除表时,使用事务处理,使得修改能立即更新到数据库文件中
      db.beginTransaction();
      try
      {
          // 重命名数据库表
          String tempTableName = TABLE_NAME + "_temp";
          String sql = "ALTER TABLE " + TABLE_NAME + " RENAME TO " + tempTableName;
          db.execSQL(sql);
    
          // 创建一个新的数据库表
          db.execSQL(sql_create_table2);
    
          // 将数据从tempTableName中插入到TABLE_NAME表中
          sql = "INSERT INTO " + TABLE_NAME + " SELECT *," + " ''FROM " + tempTableName;
          db.execSQL(sql);
    
          // 删除临时表 
          sql = "DROP TABLE " + tempTableName;
          db.execSQL(sql);
          db.setTransactionSuccessful();
      }
      finally
      {
          db.endTransaction();
      }
    
  • 使用greendao时进行数据库升级
    以下是一位国外大神的封装:

    public class MigrationHelper{
    
      private static final String    CONVERSION_CLASS_NOT_FOUND_EXCEPTION   = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
      private static MigrationHelper instance;
      public static MigrationHelper getInstance()
      {   
        if (instance == null)   {      
            instance = new MigrationHelper();   
        }   
        return instance;
      }
       /** 
          * 数据迁移 
          *  
          * @param db 
          * @param daoClasses 
          */
            public void migrate(SQLiteDatabase db, Class>... daoClasses){
              generateTempTables(db, daoClasses);// 删除旧的数据库表
              DaoMaster.dropAllTables(db, true);// 重新创建新的数据库表
              DaoMaster.createAllTables(db, false);restoreData(db, daoClasses);
            }
          /** 
            * 生成临时数据库表 
            *  
            * @param db 
            * @param daoClasses 
            */
       private void generateTempTables(SQLiteDatabase db, Class>... daoClasses){
             for (int i = 0; i < daoClasses.length; i++){
                  DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
                  String divider = "";
                  String tableName = daoConfig.tablename;
                  String tempTableName = daoConfig.tablename.concat("_TEMP");
                  ArrayList properties = new ArrayList<>();
                  StringBuilder createTableStringBuilder = new StringBuilder();
                  createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");
                  for (int j = 0; j < daoConfig.properties.length; j++){
                      String columnName = daoConfig.properties[j].columnName;
                      if (getColumns(db, tableName).contains(columnName)){
                          properties.add(columnName);
                          String type = null;
                          try{
                                type = getTypeByClass(daoConfig.properties[j].type);
                              }catch (Exception exception){
                                exception.printStackTrace();
                              }
                              createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);
                              if (daoConfig.properties[j].primaryKey){
                                  createTableStringBuilder.append(" PRIMARY KEY");
                              }
                              divider = ",";
                        }
                    }
                    createTableStringBuilder.append(");");
                    db.execSQL(createTableStringBuilder.toString());
                    StringBuilder insertTableStringBuilder = new StringBuilder();
                    insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
                    insertTableStringBuilder.append(TextUtils.join(",", properties));
                    insertTableStringBuilder.append(") SELECT ");
                    insertTableStringBuilder.append(TextUtils.join(",", properties));
                    insertTableStringBuilder.append(" FROM ").append(tableName).append(";");
                    db.execSQL(insertTableStringBuilder.toString());
                }
             }
      /** 
         * 保存数据 
         *  
         * @param db 
         * @param daoClasses 
         */
      private void restoreData(SQLiteDatabase db, Class>... daoClasses){ 
        for (int i = 0; i < daoClasses.length; i++){
              DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
              String tableName = daoConfig.tablename;
              String tempTableName = daoConfig.tablename.concat("_TEMP");
              ArrayList properties = new ArrayList();
              for (int j = 0; j < daoConfig.properties.length; j++){
                    String columnName = daoConfig.properties[j].columnName;
                    if (getColumns(db, tempTableName).contains(columnName)){
                        properties.add(columnName);
                     }
               }
          StringBuilder insertTableStringBuilder = new StringBuilder();
          insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
          insertTableStringBuilder.append(TextUtils.join(",", properties));
          insertTableStringBuilder.append(") SELECT ");
          insertTableStringBuilder.append(TextUtils.join(",", properties));
          insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
          StringBuilder dropTableStringBuilder = new StringBuilder();
          dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
          db.execSQL(insertTableStringBuilder.toString());
          db.execSQL(dropTableStringBuilder.toString());
        }
      }
    /** 
       *  获得数据库表字段类型 
       *  
       * @param type 
       * @return 
       * @throws Exception 
       */
        private String getTypeByClass(Class type) throws Exception{
          if (type.equals(String.class)) { return "TEXT"; }
          if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) { return "INTEGER"; }
          if (type.equals(Boolean.class)) { return "BOOLEAN"; }
          Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));   
          exception.printStackTrace();   
          throw exception;
        }
        /** 
           * 获得数据库所有列 
           *  
           * @param db 
           * @param tableName 
           * @return 
           */
      private static List getColumns(SQLiteDatabase db, String tableName){
        List columns = new ArrayList<>();
        Cursor cursor = null;
        try{
              cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
              if (cursor != null){
                  columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
              }
        }catch (Exception e){
              Log.v(tableName, e.getMessage(), e);
              e.printStackTrace();
         }
        finally{
            if (cursor != null) cursor.close();
        }
        return columns;
      }
    }
    
  • 最后在DaoMaster的onUpgrade内调用这个帮助类中的方法
    MigrationHelper.getInstance().migrate(db, CustomerDao.class);
    好了,greendao的使用就这么多了。

你可能感兴趣的:(greendao的使用)