2012-04-09 16 views
5

I'working en una aplicación de DB con ORmlite, mi modelo es la siguiente:¿Es bueno tener un DatabaseManager con todas las funciones de todos los objetos del modelo?

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

} 

Así que mi pregunta es, ¿es bueno tener un DatabaseManager con todas las funciones de todo objetos del modelo, como:

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

etc .....

Respuesta

2

Actualizado por el comentario de gris.

Tenga cuidado con su implementación "singleton". Su método init debe ser synchronized para asegurarse de que no termine con varias instancias de su clase DatabaseManager debido a problemas de concurrencia. Me acaba de combinar los métodos init y getInstance a la siguiente (tenga en cuenta el agregado synchronized palabra clave):

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

    return instance; 
} 

Para leer más, echa un vistazo a estos Artículos sobre Single SQLite Connection y Android Sqlite locking por Kevin Galligan (uno de los contributors a ORMlite)

Actualización:

Para responder a su pregunta sobre cómo organizar sus métodos de carga como getAllCars, me gustaría primero sugerir haciéndolos static, ya que no depende de nada más, aparte de su método para obtener su singleton de DatabaseManager, que por supuesto, también sería static. Si tiene un pequeño número de estos tipos de métodos, puede convertirlos en miembros estáticos de DatabaseManger. Si tiene muchos, podría hacer una clase auxiliar para todos los métodos estáticos correspondientes a un tipo.

Si usted tiene un método que hace dependen de los detalles internos de una instancia determinada de CarMDL o MarkMDL (como se necesita un método para conseguir algunas referencias asociadas), considerar la posibilidad de estos métodos de los miembros de la clase CarMDL o MarkMDL.

+0

I en realidad no tiene un problema con las instancias DAO en caché local. Buscarlos en DaoManager requiere una creación de objeto y no hay ninguna penalización que pueda ver. Ese es el patrón que usan todos los objetos de ejemplo. – Gray

+0

bien, combinando init y getInstance se ve bien! Pero no estoy seguro de poner todas las funciones de los modelos en una sola clase, ¿sería mejor crear otro DAO que extienda una interfaz con algunos métodos comunes? pero no estoy seguro de cómo podría ser ... Estoy un poco confundido – skabo

+0

Ver mi respuesta actualizada. – wsanville

0

Pongo todo mi trabajo de una sola vez por aplicación en Aplicación onCreate y guardo una referencia de la instancia de la aplicación en sí, así que puedo hacer muchas tareas sin tener que meterme con métodos sincronizados o similares. Así que vamos a decir que tenemos una aplicación (no olvide añadirlo en el manifiesto):

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

entonces su clase de ayuda base de datos, Manifest.class es una matriz de todas sus clases de tipos de datos:

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"); 
    } 
} 
Cuestiones relacionadas