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

Eug*_*ene 14 database android design-patterns

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

Mis*_*ith 11

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

这是我使用的:

    public interface DataAccessObject<E> {

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

    }
Run Code Online (Sandbox Code Playgroud)

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

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


Car*_*les 8

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

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

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

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

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

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

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


Kuf*_*ffs 6

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

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

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

在这里看我的帖子


Tab*_*han 6

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

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

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.
    }
Run Code Online (Sandbox Code Playgroud)