Author: Guan Hong Lam/Ghost Nuggets at fingertips: juejin.cn/user/178526… Blog: www.cnblogs.com/linguanh/ making: github.com/af913337456…

I have always been extremely averse to writing repetitive code, so I prefer to use object-oriented programming attributes to build my own wheels, or secondary wrapping.

Before the order

GreenDao believes that many Android developers are familiar with it, I do not know why, here will not introduce it, recommend their own Baidu, a lot of introduction. The day before yesterday I used Sqlite again for caching in my project, and the general code looks like this.

        Entity userInfo = schema.addEntity("UserEntity");
        userInfo.setTableName("UserInfo");
        userInfo.setClassNameDao("UserDao");
        userInfo.setJavaPackage(entityPath);
        userInfo.addIdProperty().autoincrement();
        userInfo.addIntProperty("peerId").unique().notNull().index();
        userInfo.addIntProperty("gender").notNull();
        userInfo.addStringProperty("mainName").notNull();
        userInfo.addStringProperty("pinyinName").notNull();
        userInfo.addStringProperty("realName").notNull();
        userInfo.addStringProperty("avatar").notNull();
        userInfo.addStringProperty("phone").notNull();
        userInfo.addStringProperty("email").notNull();
        userInfo.addIntProperty("departmentId").notNull();Copy the code

Write as many rows as there are columns in the table structure, and write as many columns as there are tables. GreenDao itself is very convenient, but I think it’s not convenient enough. Hence the “story”. After reading this “story”, from now on you will use GreenDao to really need your handwriting and the single table will be no more than 10 lines!

thought

Those who have done server-side development know that the data structure generally used for C/S communication is Json. When the back-end staff of your company has finished the interface, they will also provide the test interface to the front-end developer. Because I usually write the interface of my APP, I have this habit. Why not use the Json format to dynamically generate all the classes the client needs. Therefore, choose to read Json

  • GreenDao’s default main function

public class dao {

    public static void main(String[] args) throws Exception {
        /** Your generated logic */}}Copy the code
  • Parsing JSON

Since the above is a Java program, we can not use the Android Json package, we need the following several Jar packages, their function, in the Java program to use the Json operation API, we can not reference these Jar packages after parsing. This will be provided at the end of the article


dependencies {
    ...
    compile files('libs/Commons beanutils - 1.7.0. Jar')
    compile files('libs/Commons - collections - 3.2. Jar')
    compile files('libs/Commons - lang - 2.4. Jar')
    compile files('libs/Commons - logging - 1.0.4. Jar')
    compile files('libs/ezmorph - 1.0.3. Jar')
    compile files('libs/json - lib - then - jdk15. Jar')}Copy the code
  • The core function

} {“name”:” LGH “} {“name”:” LGH “}} {“name”:” LGH “}} {“name”:” LGH “}} {“name”:” LGH “}}} {“name”:” LGH “}}} So it’s a string.

private static void createTable(
            Schema schema, 
            String tableName,   / * * * / table name
            String idName,      Index / * * * /
            String json         /** Json */
    ) {
        Entity create = schema.addEntity(tableName);
        JSONObject jsonObject = JSONObject.fromObject(json);
        Iterator iterator = jsonObject.keys();
        String key;
        Object value;
        while(iterator.hasNext()){ /** iterate over Json */
            key = (String) iterator.next();  /** ** /
            value = jsonObject.get(key);
            if(value instanceof Integer){
                if(key.equals(idName)){
                    /** The primary key must be long */
                    create.addLongProperty(key).primaryKey().autoincrement();
                    continue;
                }
                create.addIntProperty(key);
            } else if (value instanceof String){
                create.addStringProperty(key).notNull();
            } else if (value instanceof Float){
                create.addFloatProperty(key).notNull();
            } else if (value instanceof Double){
                create.addDoubleProperty(key).notNull();
                /** Other types, please imitate add */
            } else{
                /** Collection type violates table structure */
                throw new IllegalFormatFlagsException("Collection type violates table structure");
            }
        }
        create.setHasKeepSections(true);
    }Copy the code
  • A case in point

import net.sf.json.JSONObject;

import java.util.IllegalFormatFlagsException;
import java.util.Iterator;

import de.greenrobot.daogenerator.DaoGenerator;
import de.greenrobot.daogenerator.Entity;
import de.greenrobot.daogenerator.Schema;

** * Author: LinGuanHong, LZQ is my dear wife. ** My GitHub: https://github.com/af913337456/ * * My Blog : http://www.cnblogs.com/linguanh/ * * on 2017/3/21. * */

/** To create a table and its field logic, you no longer need to write one by one, just pass in json */

public class dao {

    private final static String YourOutPutDirPath = "./greendaohelper/src/main/java";
    private final static String YourOutPutDirName = "dao";

    public static void main(String[] args) throws Exception {
        Schema schema = new Schema(1, YourOutPutDirName);

        String tableJson =
                "{\n" +
                " \"d_id\": 1278,\n" +         /** Integer type */
                "\"d_area\": \" America \",\n" +   /** String */
                "\"d_content\": \" Tells the story of a military hero who returns to The United States, bringing with him a lot of trouble. He'll be working with CTU to save his life or save the story of a terrorist attack on American soil. \",\n" +
                "\" d_directed \ ": \" Stephen Hopkins/strong casa/nelson it Mick/devin brown hughes \ ", \ n" +
                2.3 d_dayhits "\" \ ", \ "\", \ n" + /** Float type */
                " \"d_true_play_url\": \"xxx\"\n" +
                "}";

        createTable(
                schema,
                "pushVideo"./ * * * / table name
                "d_id"./** primary key noun */
                tableJson
        );

        createTable(
                schema,
                "lghTable"./ * * * / table name
                "id"./** primary key noun */
                "{\n" +
                " \"id\": 1278,\n" +         /** Integer type */
                "\" Name \ : \" Lin Guanhong \",\ N" +   /** String */
                "\"address\ : \" Yangjiang \",\n" +
                " \"head_url\": \"xxxxxxxx\"\n" +
                "}"
        );
        new DaoGenerator().generateAll(schema,YourOutPutDirPath);
    }

    /** o(n) */
    /** aggregate index and so on, you can override this function */
    private static void createTable( Schema schema, String tableName, String idName, String json ) {... }}Copy the code
  • The results

    At the specified path/greendaohelper/src/main/javaGenerate folderdaoAnd it contains

LghTable and pushVideo are the Bean classes we generated, and Dao is the data table configuration class, which turns out to be perfect.

expand

The above description of how to automatically and quickly generate beans, tables, and their structures using Json is not exciting enough for me.

  • Common abstraction

    Add, delete, change, check, adoptThe genericAbstract it out.

Add or update an entry

public void insertOrUpdateInfo(K entity){
    T userDao = getWirteDao();
    userDao.insertOrReplace(entity);
}Copy the code

Note that this function, which is standard insert/update a piece of data, update if it exists, insert otherwise, two generic types K and T, K is the Bean class, which is generated above, and T is the DAO data table configuration class, which is also generated above. At this point, that is, the incoming generics are automatically generated, so you don’t need to type them manually at all.

  • Generic constraint

T generics mentioned above is a configuration class belonging to Dao. After a little code analysis, it can be seen that all data table configuration classes generated by GreenDao inherit from AbstractDao class.

So, the action abstract class looks like this

public abstract class DBInterface<K.T extends AbstractDao<K.Long>> {... }Copy the code
  • A complete example

public abstract class DBInterface<K.T extends AbstractDao<K.Long>> {

    private LghLogger lghLogger = LghLogger.getLogger(DBInterface.class);

    private DBInit dbInit;

    public DBInterface(a){
        /** does not cause repeated instantiation of DBInit */
        dbInit = DBInit.instance(); /** this class provides */ at the end
    }

    protected abstract T getWirteDao(a);

    protected abstract T getReadDao(a);

    protected abstract Property getIdProperty(a);

    private void isInit(a){
        if(dbInit.getOpenHelper() == null) {throw new NullPointerException("openHelper is null!"); }}/** * Query for readable DB */
    protected DaoSession openReadableDb(a) {
        isInit();
        SQLiteDatabase db = dbInit.getOpenHelper().getReadableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        DaoSession daoSession = daoMaster.newSession();
        return daoSession;
    }

    /** * Query for writable DB */
    protected DaoSession openWritableDb(a){
        isInit();
        SQLiteDatabase db = dbInit.getOpenHelper().getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        DaoSession daoSession = daoMaster.newSession();
        return daoSession;
    }

    / * * * /
    public void insertOrUpdateInfo(K entity){
        T userDao = getWirteDao();
        userDao.insertOrReplace(entity);
    }

    public void batchInsertOrUpdateAllInfo(List<K> entityList){
        if(entityList.size() <=0 ){
            lghLogger.d("Failed to insert user info into local database, number of entries is 0");
            return ;
        }
        T userDao = getWirteDao();
        userDao.insertOrReplaceInTx(entityList);
    }



    / * * * / delete
    public void deleteOneById(int id){
        T userDao = getWirteDao();
        DeleteQuery<K> bd = userDao.queryBuilder()
                .where(getIdProperty().eq(id))
                .buildDelete();

        bd.executeDeleteWithoutDetachingEntities();
    }

    public void deleteAllBeans(a){
        T userDao =  getWirteDao();
        DeleteQuery<K> bd = userDao.queryBuilder()
                .buildDelete();
        bd.executeDeleteWithoutDetachingEntities();
    }

    / * * * /
    /** insertOrUpdate */

    /** search, add fuzzy search */
    public K getBeanById(int id){
        T dao = getReadDao();
        return dao
                .queryBuilder()
                .where(getIdProperty().eq(id)).unique();
    }

    public K getBeanWithLike(Property property,String what){
        T dao = getReadDao();
        return dao
                .queryBuilder()
                .where(property.like("%"+what+"%")).unique();
    }

    public List<K> loadAllBeans(a){
        T dao = getReadDao();
        /** 倒叙 */
        return dao.queryBuilder().orderDesc(getIdProperty()).list();
    }

    public List<K> loadAllBeansWithLike(Property property, String what){
        T dao = getReadDao();
        return dao
                .queryBuilder()
                .where(property.like("%"+what+"%")).orderAsc(getIdProperty()).list(); }}Copy the code
  • Dbinit.java takes care of initialization, static inner class singletons, avoiding repeated object creation

    public class DBInit {
    
      private LghLogger lghLogger = LghLogger.getLogger(DBInit.class);
    
      private int loginUserId = 0;
    
      private DaoMaster.DevOpenHelper openHelper;
    
      public static DBInit instance(a){
          return DBHelper.dbInit;
      }
    
      / * * private * /
      private DBInit(a){
          lghLogger.d("Initialize dbinit");
          initDbHelp(LghApp.context,1); /** You can migrate the initialization location */
      }
    
      public DaoMaster.DevOpenHelper getOpenHelper(a){
          return openHelper;
      }
    
      private static class DBHelper{
    
          private static DBInit dbInit = new DBInit();
    
      }
    
      /** It is highly recommended to use the Application context * to support the user ID to distinguish the table ** /
      public void initDbHelp(Context ctx, int loginId){
          if(ctx == null || loginId <=0) {throw  new RuntimeException("#DBInterface# init DB exception!");
          }
          /** openHelper is not null */ when switching users
          String DBName = "lgh_"+loginId+".db";
          if(openHelper! =null) {/** if db names are not the same, reset */
              String dbNameTemp = openHelper.getDatabaseName().trim();
              if(dbNameTemp.equals(DBName)){
                  lghLogger.d("Same user, no need to re-initialize local DB");
                  return;
              }else{
                  lghLogger.d("Not the same user, need to re-initialize local DB");
                  openHelper.close();
                  openHelper = null; }}if(loginUserId ! =loginId ){ loginUserId = loginId; close(); lghLogger.d("DB init,loginId: "+loginId);
              DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(ctx, DBName, null);
              this.openHelper = helper;
          }else{
              lghLogger.d("DB init,failed: "+loginId); }}private void close(a) {
          if(openHelper ! =null) {
              lghLogger.d("Close the database interface class");
              openHelper.close();
              openHelper = null;
              loginUserId = 0; }}}Copy the code
  • use

With that in mind, you’re ready to go, and there’s very little code you need to do it yourself. Let’s subclass the action type VideoInfoDbCache, integrate it with DBInterface, and rewrite the three abstract functions to look like this.

public class VideoInfoDbCache
        extends
    DBInterface<pushVideo.pushVideoDao> {

    @Override
    protected pushVideoDao getWirteDao(a) {
        return openWritableDb().getPushVideoDao(); /** This function is provided by GreenDao
    }

    @Override
    protected pushVideoDao getReadDao(a) {
        return openReadableDb().getPushVideoDao(); /** This function is provided by GreenDao
    }

    @Override
    protected Property getIdProperty(a) {
        return pushVideoDao.Properties.D_id;       /** Custom extension, where we get the general id as the main attribute */}}Copy the code

Now let’s look at the use of MainActivity. Use the anonymous object directly, directly new, directly.

public class MainActivity extends AppCompatActivity {

    List<pushVideo> list;
    List<lghTable>  lghList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); . list =new VideoInfoDbCache().loadAllBeans();
        list = new VideoInfoDbCache().loadAllBeans();
        list = new VideoInfoDbCache().loadAllBeans();
        list = new VideoInfoDbCache().loadAllBeans();
        list = new VideoInfoDbCache().loadAllBeans();
        list = new VideoInfoDbCache().loadAllBeans();

        lghList = new LghTableDbCache().loadAllBeans();
        lghList = new LghTableDbCache().loadAllBeansWithLike(
                lghTableDao.Properties.Name,"Lin Guan Hong"); . }}Copy the code

Now, is that fast enough? Is not enough? Please leave a message. I’ll repair it.

Open source github.com/af913337456… Note: When compiling the APP, it is best to unreference the json JAR of the above Java program, comment the dao.java file, and delete the build folder in the greenDaoHelper Library.