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

我正在开发一个使用SQLCipher的Android应用程序, 用于Android的ORMLite处理与SQLite和Jackson进行解析的POJO存储。

我想知道是否会有一个更好的模式,我正在使用(由stayforit推荐)获得对应于给定的实体类的DAO。 我有超过30个实体类,我不断添加一些时间,每次,我必须创建一个看起来与前一个完全相同的DAO类。 我如何使用generics类进行推广?

这是我的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> D getDAO(Class clz) throws SQLException { return dbHelper.getDao(clz); } } 

下面是每次向项目添加POJO实体时需要生成的循环DAO类的示例:

 public class CategoriesDAO extends BaseDAO { private static CategoriesDAO instance; private CategoriesDAO() { } public synchronized static CategoriesDAO getInstance() { if (instance == null) { instance = new CategoriesDAO(); } return instance; } @Override public Dao getDAO() throws SQLException, java.sql.SQLException { return DbManager.getInstance().getDAO(EntityCategories.class); } } 

以下是我在Activity中使用它的方法:

 CategoriesDAO.getInstance().addOrUpdate(categories); 

您可以将POJO daos的实例存储在BaseDao本身内部或子类中的映射中,然后使用未经检查的强制转换将其解压缩。

 public class GenericDao extends BaseDao { private static class InstanceHolder { static final Map, GenericDao> INSTANCES = new HashMap<>(); } public static synchronized  GenericDao getInstance(Class clazz) { GenericDao dao = (GenericDao)InstanceHolder.INSTANCES.get(clazz); if (dao == null) { dao = new GenericDao(); InstanceHolder.INSTANCES.put(clazz, dao); } return dao; } private GenericDao() { } } 

接着

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

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

CRUDOperator:

 public interface CRUDOperator { void create(T obj); void update(T obj); void delete(T obj); } 

回购:

 public interface Repo extends CRUDOperator{ Optional queryForId(Integer id); ObservableList queryForAll(); ... } 

OrmliteRepo:

 public class OrmliteRepo implements Repo { protected Dao dao; protected OrmliteRepo(Dao dao) { this.dao = dao; } public ObservableList queryForAll() throws SQLException { List results = dao.queryForAll(); return Validators.isNullOrEmpty(results) ? FXCollections.observableArrayList() : FXCollections.observableArrayList(results); } public Optional queryForId(Integer id) throws SQLException { T result = dao.queryForId(id); return Optional.ofNullable(result); } @Override public void create(T obj) throws SQLException { dao.create(obj); } @Override public void update(T obj) throws SQLException { dao.update(obj); } @Override public void delete(T obj) throws SQLException { dao.delete(obj); } } 

YourRepo:

 public class YourRepo extends OrmliteRepo { public YourRepo(Dao dao) { super(dao); } } 

RepoService:

 public interface RepoService {  Repo get(Class dataClass); } 

BaseRepoService:

 public class BaseRepoService implements RepoService { private RepoFactory repoFactory; private Map, Repo> repoCache; public BaseRepoService(RepoFactory repoFactory) { this.repoFactory = repoFactory; repoCache = new HashMap<>(); } @Override public  Repo get(Class dataClass) { @SuppressWarnings("unchecked") Repo repo = (Repo) repoCache.get(dataClass); if (repo == null) { repo = createRepo(dataClass); repoCache.put(dataClass, repo); } return repo; } private  Repo createRepo(Class dataClass) { return repoFactory.createRepo(dataClass); } } 

RepoFactory:

 public interface RepoFactory { public  Repo createRepo(Class dataClass); } 

OrmliteRepoFactory:

 public class OrmliteRepoFactory implements RepoFactory { private DbAccess dbAccess; private final Map, Supplier>> suppliers; public OrmliteRepoFactory(DbAccess dbAccess) { this.dbAccess = dbAccess; suppliers = new HashMap<>(); suppliers.put(YourModel.class, () -> new YourRepo(getDao(YourModel.class))); } private  Dao getDao(Class modelClass) { return dbAccess.getDaoImplementation(modelClass); } @Override @SuppressWarnings("unchecked") public  OrmliteRepo createRepo(Class dataClass) { return (OrmliteRepo) suppliers.get(dataClass).get(); } } 

DBACCESS:

 public interface DbAccess {  R getDaoImplemantation(Class dataClass); } 

OrmliteDbAccess:

 public class OrmliteDbAccess implements DbAccess{ @Override public  R getDaoImplementation(Class objectClass) { R dao = null; try { dao = DaoManager.createDao(connectionSource, objectClass); } catch (SQLException e) { LOGGER.error("Error getting dao for class {}; {}", objectClass, e); } return dao; } 

}

现在您需要做的就是将repos的供应商添加到repoFactory,并使YourRepo.class扩展为OrmliteRepo.class。 如果我需要一些特定仓库的额外行为,我会把它放在repo实现中。

当你有一个RepoService的实例时:

 RepoService repoService = new BaseRepoService(ormliteRepoFactory); 

你可以像这样访问你的回购:

 Repo repo = repoService.get(YourModel.class);