2012-04-09 7 views
5

I'working w aplikacji db z ORmlite, mój model jest tak:Czy to dobrze mieć DatabaseManager z wszystkimi funkcjami ze wszystkich obiektów modelu?

MDL obiektu ..

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

} 

Więc moje pytanie brzmi, czy to dobrze mieć DatabaseManager ze wszystkich funkcji ze wszystkich model obiektów, takich jak:

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

Etc .....

Odpowiedz

2

Aktualizacja na komentarz Greya.

Uważaj przy implementacji "singleton". Twoja metoda init powinna być synchronized, aby upewnić się, że nie kończysz z wieloma wystąpieniami klasy DatabaseManager z powodu problemów z współbieżnością. Chciałbym po prostu połączyć metody init i getInstance do poniższego (uwaga dodana synchronized słowa kluczowego):

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

    return instance; 
} 

Do dalszego czytania, sprawdź te blogach o Single SQLite Connection i Android Sqlite locking Kevin GALLIGAN (jeden z contributors do ORMlite).

Aktualizacja:

Aby odpowiedzieć na pytanie, jak zorganizować swoje metody ładowania jak getAllCars, chciałbym najpierw sugerują czyniąc je static, ponieważ nie zależy od niczego innego oprócz swojej metody, aby uzyskać pojedyncza z DatabaseManager, który oczywiście byłby również static. Jeśli masz niewielką liczbę tego typu metod, możesz uczynić je wszystkimi statycznymi członkami DatabaseManger. Jeśli masz wiele, możesz utworzyć klasę pomocniczą dla wszystkich metod statycznych odpowiadających typowi.

Jeśli masz metodę, która robi zależą od wewnętrznych danej instancji CarMDL lub MarkMDL (jak trzeba metodę, aby uzyskać pewne związane z nimi referencje), rozważyć wprowadzenie tych metod członków klasy CarMDL lub MarkMDL.

+0

I właściwie nie ma problemu z lokalnie buforowanymi instancjami DAO. Szukanie ich w DaoManager wymaga stworzenia obiektu i nie widzę żadnej kary. Jest to wzorzec, którego używają wszystkie przykładowe obiekty. – Gray

+0

ok, połączenie init i getInstance wygląda ładnie! Ale nie jestem pewien, aby umieścić wszystkie funkcje modeli w jednej klasie, czy lepiej byłoby stworzyć kolejne DAO, które rozszerzają interfejs o niektóre popularne metody? ale nie jestem pewien jak to może być ... Jestem trochę zdezorientowany – skabo

+0

Zobacz moją zaktualizowaną odpowiedź. – wsanville

0

Umieszczam wszystkie moje jednorazowe aplikacje w aplikacji onCreate i zachowuję referencję samej instancji aplikacji, dzięki czemu mogę wykonywać wiele zadań bez konieczności bałagania za pomocą metod zsynchronizowanych lub podobnych. Więc powiedzmy, że mamy aplikację (pamiętaj, aby dodać go w manifeście):

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

następnie klasa pomocnika bazy danych, Manifest.class jest tablicą wszystkich klas Typ danych:

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"); 
    } 
} 
Powiązane problemy