Jaythaking Jaythaking - 5 months ago 134
Android Question

Better pattern to handle DAO creation for POJO using SQLite

I'm working on an Android App that use SQLCipher, ORMLite for Android to handle to POJO storing with SQLite and Jackson for parsing.

I'm wondering if there would be a better pattern that the one i'm using (Recommended by stayforit) to get the DAO corresponding to the Entity class given. I have over 30 Entity class and I keep adding some over the time and each time, I have to create a DAO class that looks exactly the same as the previous one. How could I generalize using a generic class?

Here is my DbManager class:

public class DbManager {
private static DbManager instance;
private CipherDbHelper dbHelper;
private SecureSharedPreferences settings;

private DbManager() {

}

private DbManager(Context context, String password) {
SQLiteDatabase.loadLibs(context);
dbHelper = new CipherDbHelper(context, password);
}

public static void init(Context context, String password) {
instance = new DbManager(context, password);
}

public static DbManager getInstance() {
if (instance == null) {
Log.e("DbManager", "DbManager is null");
}
return instance;
}

public <D extends Dao<T, String>, T> D getDAO(Class<T> clz) throws SQLException {
return dbHelper.getDao(clz);
}
}


Here is an example of a recurrent DAO class I need to generate each time I add a POJO entity to my project:

public class CategoriesDAO extends BaseDAO<EntityCategories> {
private static CategoriesDAO instance;

private CategoriesDAO() {
}

public synchronized static CategoriesDAO getInstance() {
if (instance == null) {
instance = new CategoriesDAO();
}
return instance;
}

@Override
public Dao<EntityCategories, String> getDAO() throws SQLException, java.sql.SQLException {
return DbManager.getInstance().getDAO(EntityCategories.class);
}
}


Here is how I use it in an Activity:

CategoriesDAO.getInstance().addOrUpdate(categories);

Kal Kal
Answer

You could store the instances of your POJO daos in a map either inside your BaseDao itself or in a subclass and then use an unchecked cast to extract it out.

public class GenericDao<T> extends BaseDao<T>  {

  private static class InstanceHolder {
      static final Map<Class<?>, GenericDao<?>> INSTANCES = new HashMap<>();
  }

  public static synchronized <T> GenericDao<T> getInstance(Class<T> clazz) {
      GenericDao<T> dao = (GenericDao<T>)InstanceHolder.INSTANCES.get(clazz);
      if (dao == null) {
        dao = new GenericDao<T>();
        InstanceHolder.INSTANCES.put(clazz, dao);
      }
      return dao;
  }

  private GenericDao() {
  }
}

and then

    GenericDao<EntityCategories> foo = GenericDao.getInstance(EntityCategories.class);
    foo.addOrUpdate(....);