【问题标题】:Is it good have a DatabaseManager with all of the functions from all the model objects?拥有一个包含所有模型对象的所有功能的 DatabaseManager 是否很好?
【发布时间】:2012-04-09 20:34:58
【问题描述】:

我正在使用 ORmlite 开发一个数据库应用程序,我的模型是这样的:

MDL 对象..

DatabaseTable(tableName = "UserCars")
public class CarMDL
{
    @DatabaseField(generatedId = true)
    private int _id;

    @DatabaseField(columnName = "name")
    private String _name;

//................. etc
}

// DB Helper class...

public class DatabaseHelper extends OrmLiteSqliteOpenHelper
{
    private Dao<CarMDL,Integer> _carDao = null;

 @Override
    public void onCreate(SQLiteDatabase database,ConnectionSource connectionSource)
    {
        try 
        {
            TableUtils.createTable(connectionSource, CarMDL.class);

        } catch (SQLException e)
        {
            throw new RuntimeException(e);
        } catch (java.sql.SQLException e)
        {
            e.printStackTrace();
        }

    }

  public Dao<CarMDL, Integer> getCarDao() 
    {
        if (null == _carDao) 
        {
            try 
            {
                _carDao = getDao(CarMDL.class);

            }catch (java.sql.SQLException e) 
            {
                e.printStackTrace();
            }
        }
        return _carDao;
    }

}

// DatabaseManager class...

public class DatabaseManager
{
    static private DatabaseManager  instance;

    private DatabaseHelper  helper;


    static public void init(Context ctx)
    {
        if (null == instance)
        {
            instance = new DatabaseManager(ctx);
        }
    }

    static public DatabaseManager getInstance()
    {
        return instance;
    }

    private DatabaseManager(Context ctx)
    {
        helper = new DatabaseHelper(ctx);
    }

    private DatabaseHelper getHelper()
    {
        return helper;
    }

// All the Dao functions of all MDL objects are in this class, for example:

public List<CarMDL> getAllCars()
    {
        List<CarMDL> carLists = null;
        try
        {
            carLists = getHelper().getCarDao().queryForAll();
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return carLists;
    }

// This is another MDL object..

public List<MarkMDL> getAllMarks()
    {
        List<MarkMDL> marks = null;
        try
        {
            marks = getHelper().getMarkDao().queryForAll();
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return marks;       
    }

}

所以我的问题是,拥有一个包含所有模型对象的所有功能的 DatabaseManager 是否很好,例如:

listCarById(int id)
listPlaneById(int id)
removeCar(int id)
removePlane(int id)

等等……

【问题讨论】:

    标签: java android database-design ormlite


    【解决方案1】:

    根据格雷的评论更新。

    小心你的“单例”实现。您的init 方法应该是synchronized,以确保您不会因为并发问题而得到DatabaseManager 类的多个实例。我只需将initgetInstance 方法组合到以下内容(注意添加的synchronized 关键字):

    public static synchronized DatabaseManager getInstance(Context c)
    {
        if(instance == null)
            instance = new DatabaseManager(c);
    
        return instance;
    }
    

    如需进一步阅读,请查看 Kevin Galligan 撰写的关于 Single SQLite ConnectionAndroid Sqlite locking 的这些博客文章(ORMlite 的 contributors 之一)。

    更新:

    要回答有关如何组织 getAllCars 之类的加载方法的问题,我首先建议将它们设为 static,因为除了您获取 DatabaseManager 单例的方法之外,它们不依赖于其他任何东西,即当然,也可以是static。如果您有少量这些类型的方法,您可以将它们全部设为DatabaseManger 的静态成员。如果你有很多,你可以为一个类型对应的所有静态方法创建一个帮助类。

    如果您有一个方法确实依赖于CarMDLMarkMDL 的给定实例的内部(就像您需要一个方法来获取一些关联的引用),请考虑使用这些方法CarMDLMarkMDL 类的成员。

    【讨论】:

    • 我其实对本地缓存的DAO实例没有问题。在 DaoManager 中查找它们需要创建对象,并且我看不到任何惩罚。这是所有示例对象都使用的模式。
    • 好的,将 init 和 getInstance 结合起来看起来不错!但是我不确定将所有模型函数放在一个类中,创建另一个使用一些常用方法扩展接口的 DAO 会更好吗?但我不确定这是怎么回事......我有点困惑
    【解决方案2】:

    我将我所有的每个应用程序一次性工作都放在 Application onCreate 中,并保留应用程序实例本身的引用,因此我可以执行许多任务而不必弄乱同步方法或类似方法。所以假设我们有一个应用程序(记得在清单中添加它):

    public class App extends Application
    {
        private static App gInstance = null;
        // your static globals here
    
        @Override
        public void onCreate()
        {
            // according to documentation onCreate is called before any other method
            super.onCreate();
            // assign here all your static stuff
            gInstance = this;
        }
    
        // doesn't need to be synchronized because of the early onCreate
        public static App getInstance()
        {
            return gInstance;
        }
    }
    

    那么你的数据库助手类,Manifest.class 是你所有数据类型类的数组:

    public class DatabaseHelper extends OrmLiteSqliteOpenHelper
    {
        // private constructor, singleton pattern, we use
        // App context so the class is created on static init
        private static DatabaseHelper gHelper = new DatabaseHelper(App.getInstance());
    
        private DatabaseHelper(Context context)
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION, R.raw.ormlite_config);
    
            // cache your dao here
            for (Class<?> cls: Manifest.classes)
            {
                try
                {
                    DaoManager.createDao(getConnectionSource(), cls);
                } catch (SQLException e)
                {
                    e.printStackTrace();
                }
            }
        }
    
        // if you need the instance, you don't need synchronized because of static init
        public static DatabaseHelper getHelper()
        {
            return gHelper;
        }
    
        // lookup from cache
        public static <D extends Dao<T, ?>, T> D getTypeDao(Class<T> cls)
        {
            return DaoManager.lookupDao(gHelper.getConnectionSource(), cls);
        }
    
        // we leak this class here since android doesn't provide Application onDestroy
        // it's not really a big deal if we need the orm mapping for all application lifetime
        // Q: should I keep the instance closeable? the android finalyzer calls somehow close here? I was unable to reproduce, to be sure you can call the super.close() and print a warning
        @Override
        public void close()
        {
            throw new RuntimeException("DatabaseHelper Singleton is ethernal");
        }
    }
    

    【讨论】:

      【解决方案3】:

      将上下文添加到您的 DatabaseManager 方法中

         @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              DatabaseManager.init(this.getContext());
              if (getArguments() != null) {
                  mParam1 = getArguments().getString(ARG_PARAM1);
                  mParam2 = getArguments().getString(ARG_PARAM2);
              }
          }
      

      带有 ormlite 的示例 android 应用程序 https://github.com/elberthcabrales/cfeMedicion

      【讨论】:

        猜你喜欢
        • 2011-12-26
        • 1970-01-01
        • 2021-10-24
        • 2013-06-05
        • 2016-02-08
        • 2015-03-28
        • 2015-06-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多