Java 使用SQLite处理POJO DAO创建的更好模式

Java 使用SQLite处理POJO DAO创建的更好模式,java,android,sqlite,design-patterns,ormlite,Java,Android,Sqlite,Design Patterns,Ormlite,我正在开发一个Android应用程序,它使用SQLCipher,或Android的mlite来处理使用SQLite存储的POJO,并使用Jackson进行解析 我想知道是否有一个更好的模式,我正在使用(推荐)的模式来获得与给定实体类对应的DAO。我有30多个实体类,我一直在添加一些实体类,每次我都必须创建一个看起来与前一个完全相同的DAO类。如何使用泛型类进行泛化 这是我的DbManager类: public class DbManager { private static DbMana

我正在开发一个Android应用程序,它使用SQLCipher或Android的mlite来处理使用SQLite存储的POJO,并使用Jackson进行解析

我想知道是否有一个更好的模式,我正在使用(推荐)的模式来获得与给定实体类对应的DAO。我有30多个实体类,我一直在添加一些实体类,每次我都必须创建一个看起来与前一个完全相同的DAO类。如何使用泛型类进行泛化

这是我的DbManager类:

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);
    }
}

您可以将POJO DAO的实例存储在BaseDao本身内部或子类中的映射中,然后使用未经检查的强制转换将其提取出来

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() {
  }
}
公共类GenericDao扩展了BaseDao{
私有静态类InstanceHolder{
静态最终映射>实例=新HashMap();
}
公共静态同步GenericDao getInstance(类clazz){
GenericDao=(GenericDao)InstanceHolder.INSTANCES.get(clazz);
if(dao==null){
dao=新的GenericDao();
InstanceHolder.INSTANCES.put(clazz,dao);
}
返回道;
}
私有GenericDao(){
}
}
然后

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

您可以将POJO DAO的实例存储在BaseDao本身内部或子类中的映射中,然后使用未经检查的强制转换将其提取出来

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() {
  }
}
公共类GenericDao扩展了BaseDao{
私有静态类InstanceHolder{
静态最终映射>实例=新HashMap();
}
公共静态同步GenericDao getInstance(类clazz){
GenericDao=(GenericDao)InstanceHolder.INSTANCES.get(clazz);
if(dao==null){
dao=新的GenericDao();
InstanceHolder.INSTANCES.put(clazz,dao);
}
返回道;
}
私有GenericDao(){
}
}
然后

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

这就是我喜欢使用Ormlite DAO的方式:

积垢器:

public interface CRUDOperator<T> {

    void create(T obj);

    void update(T obj);

    void delete(T obj);
}
您可以通过以下方式访问您的回购:

Repo<YourModel> repo = repoService.get(YourModel.class);
Repo-Repo=repoService.get(YourModel.class);

这就是我喜欢使用Ormlite DAO的方式:

积垢器:

public interface CRUDOperator<T> {

    void create(T obj);

    void update(T obj);

    void delete(T obj);
}
您可以通过以下方式访问您的回购:

Repo<YourModel> repo = repoService.get(YourModel.class);
Repo-Repo=repoService.get(YourModel.class);

您可以将橱柜作为ORMLite的替代品@cricket_007看起来不错,但我需要能够处理特定ORM不支持的嵌套对象(单对多关系)…请检查。JDXA可以处理嵌套对象,并且不需要为每个实体(模型)类创建DAO类@cricket_007看起来不错,但我需要能够处理特定ORM不支持的嵌套对象(单对多关系)…请检查。JDXA可以处理嵌套对象,不需要为每个实体(模型)创建DAO类这看起来很有趣,但对于我最初的目标来说有点过火了。我的目标是简化和缩短代码。当涉及到简单的问题时,我并不总是相信复杂模式的使用……但是也许你是对的,如果我想换到其他库而不是ORMLite,那么这就允许模块化……你完全正确。对于你的用例来说,这太过分了。但是关于你问题的一般性质,我认为这个模式可能有用。(我正在胶子多平台项目中使用它,因此使用了接口)这看起来很有趣,但对于我最初的目标来说有点过分了,我的目标是简化和缩短代码。当涉及到简单的问题时,我并不总是相信复杂模式的使用……但也许你是对的,这允许模块化,以防我想换到其他库而不是ORMLite……你完全正确。对于你的用例来说,这太过分了。但是关于你问题的一般性质,我认为这个模式可能有用。(我正在一个胶子多平台项目中使用它,因此使用了接口)我将尝试一下,谢谢!未经检查的强制转换是一种不好的做法,还是我不应该为此烦恼?@Jaythaking一般来说,未经检查的强制转换可能是危险的。但是在这个特定的用例中,您知道,您在映射中放入的基本上只是一个包含类名和实例的键值对。。所以你知道你会得到什么。我会试试的,谢谢!未经检查的强制转换是一种不好的做法,还是我不应该为此烦恼?@Jaythaking一般来说,未经检查的强制转换可能是危险的。但是在这个特定的用例中,您知道,您在映射中放入的基本上只是一个包含类名和实例的键值对。。所以你知道你会得到什么。
public interface RepoService {
    <T> Repo<T> get(Class<T> dataClass);
}
public class BaseRepoService implements RepoService {

    private RepoFactory            repoFactory;
    private Map<Class<?>, Repo<?>> repoCache;

    public BaseRepoService(RepoFactory repoFactory) {
        this.repoFactory = repoFactory;
        repoCache = new HashMap<>();
    }

    @Override
    public <T> Repo<T> get(Class<T> dataClass) {
        @SuppressWarnings("unchecked")
        Repo<T> repo =  (Repo<T>) repoCache.get(dataClass);

        if (repo == null) {
            repo = createRepo(dataClass);
            repoCache.put(dataClass, repo);
        }
        return repo;
    }

    private <T> Repo<T> createRepo(Class<T> dataClass) {
        return repoFactory.createRepo(dataClass);
    }
}
public interface RepoFactory {
    public <T> Repo<T> createRepo(Class<T> dataClass);
}
public class OrmliteRepoFactory implements RepoFactory {

    private DbAccess                                      dbAccess;
    private final Map<Class<?>, Supplier<OrmliteRepo<?>>> suppliers;

    public OrmliteRepoFactory(DbAccess dbAccess) {
        this.dbAccess = dbAccess;

        suppliers = new HashMap<>();
        suppliers.put(YourModel.class, () -> new YourRepo(getDao(YourModel.class)));
    }

    private <T> Dao<T, Integer> getDao(Class<T> modelClass) {
        return dbAccess.getDaoImplementation(modelClass);
    }

    @Override
    @SuppressWarnings("unchecked")
    public <T> OrmliteRepo<T> createRepo(Class<T> dataClass) {
        return (OrmliteRepo<T>) suppliers.get(dataClass).get();
    }
}
public interface DbAccess {
     <T, R> R getDaoImplemantation(Class<T> dataClass);
}
public class OrmliteDbAccess implements DbAccess{

@Override
public <T, R> R getDaoImplementation(Class<T> objectClass) {
    R dao = null;

    try {
        dao = DaoManager.createDao(connectionSource, objectClass);

    } catch (SQLException e) {
        LOGGER.error("Error getting dao for class {}; {}", objectClass, e);
    }
    return dao;
}
RepoService repoService = new BaseRepoService(ormliteRepoFactory);
Repo<YourModel> repo = repoService.get(YourModel.class);