创建greenDAO数据库连接的最佳方法是仅在应用程序单次运行期间创建一次连接?

3

目前我正在创建一个类中的greenDAO DB连接(该类在每个静态方法中打开连接),并在需要时使用它。但我不确定这是否是最佳做法。 有人可以建议更好的方法吗?

我的代码:

import com.knowlarity.sr.db.dao.DaoMaster;
import com.knowlarity.sr.db.dao.DaoMaster.DevOpenHelper;
import com.knowlarity.sr.db.dao.DaoSession;
import com.knowlarity.sr.db.dao.IEntity;

public class DbUtils {

    private static Object lockCallRecord =new Object();
    private DbUtils(){};

    public static boolean saveEntity(Context context , IEntity entity){
            boolean t=false;
            DevOpenHelper helper=null;
            SQLiteDatabase db=null;
            DaoMaster daoMaster=null;
            DaoSession daoSession =null;
            try{
               helper = new DaoMaster.DevOpenHelper(context, IConstant.DB_STRING, null);
               db = helper.getReadableDatabase();
               daoMaster = new DaoMaster(db);
               daoSession = daoMaster.newSession();
               //Some business logic here for fetching and inserting the data.
            }catch (Exception e){
               Log.e("saveEntity", e.getStackTrace().toString());
            }finally{
               if(daoSession!=null)daoSession.clear();
               daoMaster=null;
               if(db.isOpen())db.close();
               helper.close();
            }
            return t;
    }

@stack 我已经添加了代码。 - Anuj
请查看此教程:http://wiki.workassis.com/android-greendao-example/ - Bikesh M
2个回答

10
你的方法会频繁加载数据库,这是不必要的,可能会显著降低应用程序速度。
打开数据库一次并将其存储在某个地方,在需要时从那里请求它。
我个人使用全局DaoSession和本地DaoSessions。本地DaoSessions用于不应保留在会话缓存中的情况下(例如将新对象持久化到数据库中,可能仅很少使用,或执行将加载许多不太可能再次重用的实体的某些查询)。
请注意,如果您在全局会话中也使用实体,则在本地DaoSession中更新实体是一个坏主意。如果您这样做,则全局会话中的缓存实体将不会更新,除非您清除全局会话的缓存!因此,最安全的方法是只使用一个DaoSession或始终使用新的DaoSessions,而不使用全局和本地会话!
自定义应用程序类是一个好地方,但任何其他类也都可以。
以下是我的做法:
class DBHelper:
private SQLiteDatabase _db = null;
private DaoSession _session = null;

private DaoMaster getMaster() {
    if (_db == null) {
        _db = getDatabase(DB_NAME, false);
    }
    return new DaoMaster(_db);
}

public DaoSession getSession(boolean newSession) {
    if (newSession) {
        return getMaster().newSession();
    }
    if (_session == null) {
        _session = getMaster().newSession();
    }
    return _session;
}

private synchronized SQLiteDatabase getDatabase(String name, boolean readOnly) {
    String s = "getDB(" + name + ",readonly=" + (readOnly ? "true" : "false") + ")";
    try {
        readOnly = false;
        Log.i(TAG, s);
        SQLiteOpenHelper helper = new MyOpenHelper(context, name, null);
        if (readOnly) {
            return helper.getReadableDatabase();
        } else {
            return helper.getWritableDatabase();
        }
    } catch (Exception ex) {
        Log.e(TAG, s, ex);
        return null;
    } catch (Error err) {
        Log.e(TAG, s, err);
        return null;
    }
}

private class MyOpenHelper extends DaoMaster.OpenHelper {
    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i(TAG, "Create DB-Schema (version "+Integer.toString(DaoMaster.SCHEMA_VERSION)+")");
        super.onCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.i(TAG, "Update DB-Schema to version: "+Integer.toString(oldVersion)+"->"+Integer.toString(newVersion));
        switch (oldVersion) {
            case 1:
                db.execSQL(SQL_UPGRADE_1To2);
            case 2:
                db.execSQL(SQL_UPGRADE_2To3);
                break;
            default:
                break;
        }
    }
}

在应用程序类中:

private static MyApplication _INSTANCE = null;

public static MyApplication getInstance() {
    return _INSTANCE;
}

@Override
public void onCreate() {
    _INSTANCE = this;
    // ...
}

private DBHelper _dbHelper = new DBHelper();

public static DaoSession getNewSession() {
    return getInstance()._dbHelper.getSession(true);
}

public static DaoSession getSession() {
    return getInstance()._dbHelper.getSession(false);
}

当然,您也可以存储DaoMaster而不是数据库本身。这将减少一些小的开销。

我使用类似单例的Application类和静态方法来避免每次使用某些常用方法(比如访问数据库)时都需要进行应用程序强制类型转换(((MyApplication)getApplication()))。


1
@WindRider 简单来说,我的使用情况是在某个时间需要查询大量数据。用户选择了其中一个,之后我在接下来的1小时内不再需要这些数据。因此,我不想将这些数据存储在我的会话缓存中。 - AlexS
1
@WindRider 关于你的方法:如果你在两个会话中的一个中写入数据到数据库,那么这些会话可能是不一致的,因为另一个会话没有被通知到这些更改并且保留了过时的实体。也许使用同一个会话是可以的。正如之前所说,使用两个会话的方法是为了一个非常特殊的用例而设计的。 - AlexS
我打算使用一个全局会话,并在需要大量加载行时使用内容提供程序,这被证明非常快速。希望不必对修改使用内容提供程序,这应该为缓存一致性给我一些保证。因此,DAO 用于读/写,内容提供程序用于只读。 - WindRider
1
@WindRider 如果您的第二个(本地)会话仅用于一次读取,则保持一致。否则,您可能会读取过时的数据。为什么不使用相同的会话? - AlexS
是的,我认为一个全局会话是我的选择。但如果内容提供者更新了已经缓存的行,则仍然可能会出现问题。一种方法是在来自内容提供者的每个可能的修改之后清除缓存。 - WindRider
显示剩余2条评论

0
我建议在你的Application类中创建数据库。然后,你可以创建一个方法来返回DaoSession以便在其他活动中访问数据库。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接