Каков наилучший способ создания подключения к базе данных greenDAO только один раз для одного запуска приложения?

В настоящее время я создаю соединение с базой данных greenDAO в классе (который открывает соединение в каждом статическом методе) и использую его везде, где мне это нужно. Но я не уверен, что это лучший способ сделать это. Кто-нибудь может предложить лучший способ сделать это?

Мой код:

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

2 ответа

Решение

Ваш подход приводит к тому, что база данных загружается очень часто, что не является необходимым и может значительно замедлить работу вашего приложения.

Откройте базу данных один раз, сохраните ее где-нибудь и запросите ее оттуда, если необходимо.

Лично я пользуюсь глобальным DaoSession и местный DaoSession s. Местный DaoSession s используются там, где ничего не должно оставаться в кэше сеанса (т. е. при сохранении нового объекта в базе данных, который, вероятно, будет использоваться только очень редко, или при выполнении некоторых запросов, которые будут загружать множество объектов, которые вряд ли будут снова использованы повторно).

Имейте в виду, что обновление сущностей в локальном DaoSession плохая идея, если вы используете сущность и в глобальном сеансе. Если вы сделаете это, кэшированная сущность в вашем глобальном сеансе не будет обновлена, и вы получите неверные результаты, если не очистите кэш глобального сеанса!

Таким образом, самый безопасный способ это либо просто использовать один DaoSession или новый DaoSession s все время и не использовать глобальные и локальные сеансы!!!

Пользовательский класс приложения - это хорошее место, но любой другой класс тоже подойдет.

Вот как я это делаю:

Класс 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())) каждый раз, когда я использую некоторые распространенные методы (например, доступ к БД).

Я бы порекомендовал создать вашу базу данных в вашем классе приложений. Затем вы можете создать метод для возврата DaoSession, чтобы получить доступ к базе данных в других действиях.

Другие вопросы по тегам