【问题标题】:Is it OK to use static "database helper" class?可以使用静态“数据库助手”类吗?
【发布时间】:2011-02-27 09:27:39
【问题描述】:

我有一些 Android 项目,其中大部分都与 SQLite 数据库 相关联。我感兴趣的是使用一些像“DatabaseHelper.class”这样的静态类是一种好的编程习惯(或坏习惯),我将在其中拥有与数据库操作相关的所有静态方法。例如

public static int getId(Context context, String name) {
    dbInit(context);

    Cursor result = db.rawQuery("SELECT some_id FROM table WHERE some_name = '" + name + "'", null);
    result.moveToFirst();
    int id = result.getInt(result.getColumnIndex("some_id"));
    result.close();

    return id;
}

dbInit(context) (在我所有的数据库操作静态方法中使用)

private static void dbInit(Context context) {
    if (db == null) {
        db = context.openOrCreateDatabase(DATABASE_NAME, Context.MODE_PRIVATE, null);
    }
}

然后,当我需要某些东西时,我可以轻松地调用这些方法,例如

int id = DatabaseHelper.getId(this, "Abc");

编辑:我必须在每个连接上使用 dbClos​​e 还是让它按活动打开并关闭每个活动?那我有没有把上面的代码改成这样?

    ...
    dbClose();

    return id;
}

private static void dbClose() {
    if (db != null) {
        db.close();
    }
}

【问题讨论】:

    标签: java android sqlite


    【解决方案1】:

    我建议你养成每次需要数据库连接的习惯,并在完成后释放它。这种设施的通常名称是“数据库连接池”。

    这会将连接逻辑从您的实际代码中移到池中,并允许您在以后需要时做很多事情。一件简单的事情,可能是池记录了连接对象的使用时间,因此您可以获得有关数据库使用情况的信息。

    如果您只需要一个连接,您的初始池可以非常简单。

    【讨论】:

    • 一个池对于仅仅一个 sqlite 连接来说是多余的,因为打开这些连接只需要 0.2 毫秒,所以这样做但跳过池
    【解决方案2】:

    我肯定会将与数据库相关的代码放在一个单独的类中,但我真的建议不要使用静态类或 Singleton。由于方便,它一开始可能看起来不错,但不幸的是,它紧密耦合了您的类,隐藏了它们的依赖关系,并且还使单元测试变得更加困难。

    维基百科中的drawbacks 部分简要概述了您可能想要探索其他技术的原因。您也可以前往over hereover there,他们提供了使用数据库访问单例的类的具体示例,以及如何使用依赖注入来解决我提到的一些问题。

    作为第一步,我建议使用您在构造函数中实例化的普通类,例如:

    public class MyActivity extends Activity {    
      private DBAccess dbAccess;
      public MyActivity() {
         dbAccess = new DBAccess(this);
      }    
    }
    

    作为第二步,您可能想要研究像 RoboGuice 这样的框架来打破硬依赖。你的代码看起来像:

    public class MyActivity extends Activity {    
      @Inject private DBAccess dbAccess;
      public MyActivity() {
      }    
    }
    

    如果您想了解更多详情,请告诉我们!

    【讨论】:

      【解决方案3】:

      如果您要使用单例,最低要求是使其无状态/线程安全。如果您使用 getId 方法,因为它代表并发调用可能会导致各种奇怪的错误...

      dbInit(context);
      

      可以为线程 A 调用,然后在命中查询语句之前停止处理。随后线程 B 执行 getId 并同时调用 dbInit 传递不同的上下文。然后线程 A 将恢复并尝试在 B 的上下文中执行查询。

      也许这在您的应用程序中不是问题,但我建议在该 getId 方法上添加一个同步修饰符!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-15
        相关资源
        最近更新 更多