我从SQLiteOpenHelper派生的类变得越来越大

我从SQLiteOpenHelper派生的类在一段时间内变得越来越大。 在发言时间,超过1500行代码不被认为是酷的。 可能有一些优雅的解决方案来防止它的增长,即通过和平分离。 不确定那些和平是什么。 有些人说inheritance上述类是一种不好的做法,因为它会导致数据库创建/升级过程的不当行为。 任何提示? 非常感谢!

Related of "我从SQLiteOpenHelper派生的类变得越来越大"

是的,开发中显示的示例。 site确实鼓励创建一个怪物类,你可以在其中对每个表和列的名称进行硬编码。 这是一团糟。 您可能想要创建一个类来处理每个表。 这些类可以充当每个表的数据访问对象 。

这是我用的:

  public interface DataAccessObject { public void onCreate(SQLiteDatabase db); public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion); public void create(E... params); public E[] retrieve(E... params); public void update(E... params); public void delete(E... params); } 

然后我为每个表编写一个实现。 通用条纹E通常是pojos。 请注意,我并没有将用于保存数据(pojos)的类与负责持久检索数据(DAO)的类混合在一起。 例如,pojo可以是Car ,其variables(颜色,年份等)。 然后我编写一个扩展DataAccessObject的CarDAO代码。 这个DAO类负责将pojo的variables映射到DB列,查询表并写入它。

最后,您可以拥有一个注入DAO的SQLiteOpenHelper,并将每个表的内容委托给它们。 这些DAO实现是具有表和列名称常量的实现。 如果需要一些复杂的查询,他们可以互相交谈。 (注意这也是这种方法的缺点之一:当你需要涉及许多表和列的查询时,产生一个简洁的设计并不简单)。

您应该尽可能避免将所有特定于模型的代码放入助手中。 把它想象成你可以在下一个项目中尽可能多地重用的东西。 您可以遵循一些常见的数据抽象模式和原则。

  • 例如,您可以考虑Active Record ,其中包含业务对象,其字段和方法,以及与持久性相关的所有方法(从数据库读取和写入)。
  • 此外,您可以考虑一个轻量级对象,并将实例保存到数据库中,并通过其他一些提供映射function的对象将其保存到数据库中,这样的实体管理器就像一些ORM一样。
  • 您还可以看一下Zend TableGateway ,它是将数据库表作为对象表示的一种很酷的方法,您可以迁移到android和sqlite。
  • 您可以使用基于水化器的简单而强大的解决方案,如下所述

就个人而言,我更喜欢使用Hydrators

这是一个在一些ORM中广泛使用的概念,也在本机Zend Framework中,以及在其他系统中提供数据持久性,这是为了帮助对象甚至Web表单以易于理解和维护的方式映射到数据库记录。

水化器是将一侧的数据库字段名称映射到另一侧的实体属性的对象。 它不会在内部存储此信息,但提供了从数据库创建对象以及从对象中提取数据集以更新数据库的机制。
可以像具有列名称数组的对象一样简单 – >实体属性,并且当调用其YourClass hydrate()方法时,将相应的信息从数据源传输到模型对象,以及extract(YourClass yourObject)调用extract(YourClass yourObject)方法,它将yourObject中包含的数据传输到相应的数据库记录

我非常喜欢这种方法,因为创建一个接口非常容易,而且常见的用例也有很多实现。 因此,您可以在不影响主要对象或帮助程序的情况下对数据库执行更改 。 此外,使用相同的界面, 您可以创建映射器以将数据导出到json,xml,rest调用或您可以想象的任何其他内容

如果你能想到一个好的保湿器设计,然后创建一些inheritance的类,你可以拥有一个非常小的数据库帮助器,真正的小实体对象,一些抽象的类做共同的工作,以及一些可以得到所有重量的混凝土加油器可能需要,但从来没有那么多,因为你可以为每个表或对象types都有一个,所以这些类明显更小,而且,它们只包含在业务级别相关的代码。

你的助手不应该那么大。 我只能假设您将所有操作数据的代码放入Helper中。

您应该将代码放在与其相关的类中以及可以以面向对象的方式访问它的位置。

例如,如果您有一个Contacts类。 您可以将保存联系人的代码放入其中的数据库中。

在这里看我的post

我按照给定的代码片段进行操作:

SQLHelper类:

  public class SQLHelper extends SQLiteOpenHelper { public SQLHelper(Context context, String DBName) { super(context, DBName, null, DATABASE_VERSION); } public SQLiteDatabase getDBObject(int isWrtitable) { return (isWrtitable == 1) ? this.getWritableDatabase() : this.getReadableDatabase(); } @Override public void onOpen(SQLiteDatabase db) { super.onOpen(db); onCreate(db); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(TABLE_1); db.execSQL(TABLE_2); ... db.execSQL(TABLE_N); } } 

MySQLManager:大部分工作都是:

  public class MySQLManager { private SQLHelper sqlHelper; //Singlton class public void initMySQLManager(Context context, String DBName) { _context = context; sqlHelper = new DBHandler(context, DBName); } public MyObject getMyObjectRecord() { MyObject myObj = new MyObject(); Cursor cursor = null; try { cursor = dbObject.getWritableDatabase().rawQuery("select * FROM " + SQLHelper.MYOBJECT_TABLE + ";", null); //fetch things } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null && !cursor.isClosed()) { cursor.close(); } } return bookVo; } //Similarly other methods. } 

您可以考虑单例类只打开和关闭数据库连接(或者像池一样捕获,释放)然后像命令模式一样使用命令类执行数据库操作

并且您可以使用facade模式以执行顺序合并此命令,以执行更复杂的数据库操作。这将使您的代码清晰且易于控制。 比如当你改变你的InsertBookCommand类时,所有相关的操作都会改变它的行为。

总之,我的解决方案是:

打开数据库连接并将db作为parameter passing给命令。 然后执行命令。