ORMLiteを使用したAndroidのORM

現時点では、データベースを操作するためのORMアプローチの実装を可能にするAndroidプラットフォーム用のソリューションがいくつかありますが、主に2つあります。 これらはORMLiteGreenDAOです。



初心者にとっては、一歩後退して、ORMの一般的な内容を伝える価値があります。 ORM-オブジェクトとリレーショナルのマッピング。 オブジェクトリレーショナルマッピングは、 リレーショナルデータベースにデータを格納するテーブルよりも、アプリケーションで使用するオブジェクトを操作する方がプログラマにとってはるかに便利であることを意味します 。 ORMテクノロジーは、リレーショナルDBMSをアプリケーションオブジェクトモデルに接続するために使用されます。 したがって、Androidのオブジェクトリレーショナルマッピングの問題を解決するには、サードパーティのフレームワークのいずれかを使用します。 GreenDAOとORMLiteはオープンソースのライブラリです。





グリーンダオ


アプリケーションで使用するドイツの開発者によるフレームワーク。



利点:


Reflectionを使用て動作しません

Android ORMの最大パフォーマンス

最小限のメモリ使用量

ライブラリのサイズが小さいことは、Androidプロジェクトに大きな影響を与えません。

短所:






ORMLite


Androidに適合したバージョンを備えた人気のあるJavaフレームワーク。



利点:




短所:


...うーん...私はそれらを見つけませんでした)不可能と思われるすべては、ドックのより深い研究で実現されます。



私はいくつかのプロジェクトでOrmLiteを使用していますが、かなり詳しく知っています。 したがって、私はちょうど彼の周りに座ります。



単純なクラス注釈



作成するデータベースへのマッピング(データベースへの保存)ごとに注釈を付ける必要があります。 ( class-configurationを使用できますが、これはまったく別の話です)クラスには必ず引数のないコンストラクターが必要であることに注意してください。 注釈の例:



@DatabaseTable(tableName = "goals") public class Goal{ public final static String GOAL_NAME_FIELD_NAME = "name"; @DatabaseField(generatedId = true) private int Id; @DatabaseField(canBeNull = false, dataType = DataType.STRING, columnName = GOAL_NAME_FIELD_NAME) private String name; @DatabaseField(dataType = DataType.DATE) private Date lastEditDate; @DatabaseField() private String notes; public Goal(){ scheduleList = new ArrayList<Shedule>(); priorities = new ArrayList<PrioritySchedule>(); } }
      
      







最初の注釈@DatabaseTable(tableName = "goals")



は、このクラスのオブジェクトが表示されるテーブルの名前を示します。

各フィールドには、さまざまな引数を持つ@DatabaseField



アノテーションが必要です。 (引数を省略することもできます-デフォルトですべてが設定され、テーブルの列名はフィールド名と一致します)。 名前フィールドには3つの引数があります。 canBeNull = false



は、この列をテーブル内で空にできないことを意味します。 dataType = DataType.STRING



列の型をString



dataType = DataType.STRING



ことを強制します。 (利用可能なタイプはこちらにあります )。 columnName = GOAL_NAME_FIELD_NAME



テーブル内の列名を強制することは、データベースからデータを取得するための選択クエリを作成するときに将来役立つでしょう。

主キーには任意のフィールドを指定できます。id id = true



指定するだけですが、 id = true



- generatedId = true



id値をgeneratedId = true



設定することをお勧めしgeneratedId = true



。 ORMLite自体が彼に一意の番号を割り当てます。

データベースの列にインデックスを付けるには、 index = true





利用可能なすべてのフィールドアノテーション引数の詳細な説明は、 ここにあります。

また、ORMLiteアノテーションに加えて、通常のjavax.persistenceアノテーションを使用できます



AndroidでSQLiteに接続する



AndroidでORMLiteを使用してデータベースデータにアクセスするには、いくつかの方法があります。 ORMLiteBaseActivityからすべてのアクティビティを継承できます。データベースに接続するライフサイクルに従う必要はありませんが、他のクラスからアクセスすることはできません。 ( 例を参照

以下で説明するアプローチの方がはるかに望ましい方法です。



データベースの作成および操作でアシスタントをインスタンス化するクラスを作成する必要があります。



 public class HelperFactory{ private static DatabaseHelper databaseHelper; public static DatabaseHelper getHelper(){ return databaseHelper; } public static void setHelper(Context context){ databaseHelper = OpenHelperManager.getHelper(context, DatabaseHelper.class); } public static void releaseHelper(){ OpenHelperManager.releaseHelper(); databaseHelper = null; } }
      
      







アプリケーションへのアクセスは、アプリケーションの存続期間の最初と最後に発生します。

これにより、開いているデータベース接続によるメモリリークが防止されます。



 public class MyApplication extends Application{ @Override public void onCreate() { super.onCreate(); HelperFactory.setHelper(getApplicationContext()); } @Override public void onTerminate() { HelperFactory.releaseHelper(); super.onTerminate(); } }
      
      







また、マニフェストでアプリケーションサクセサをクラスに記述することを忘れないでください。



  <application android:name=".MyApplication" android:icon="@drawable/ic_launcher" android:label="@string/app_name" >
      
      







データベースを作成し、DAOへのリンクを取得するDataBaseHelperクラスを作成しましょう。



 public class DatabaseHelper extends OrmLiteSqliteOpenHelper{ private static final String TAG = DatabaseHelper.class.getSimpleName(); //        /data/data/APPNAME/DATABASE_NAME.db private static final String DATABASE_NAME ="myappname.db"; //   ,            onUpgrade(); private static final int DATABASE_VERSION = 1; //  DAO  ,    private GoalDAO goalDao = null; private RoleDAO roleDao = null; public DatabaseHelper(Context context){ super(context,DATABASE_NAME, null, DATABASE_VERSION); } //,         @Override public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource){ try { TableUtils.createTable(connectionSource, Goal.class); TableUtils.createTable(connectionSource, Role.class); } catch (SQLException e){ Log.e(TAG, "error creating DB " + DATABASE_NAME); throw new RuntimeException(e); } } //,        @Override public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVer, int newVer){ try{ //  ,         TableUtils.dropTable(connectionSource, Goal.class, true); TableUtils.dropTable(connectionSource, Role.class, true); onCreate(db, connectionSource); } catch (SQLException e){ Log.e(TAG,"error upgrading db "+DATABASE_NAME+"from ver "+oldVer); throw new RuntimeException(e); } } //  GoalDAO public GoalDAO getGoalDAO() throws SQLException{ if(goalDao == null){ goalDao = new GoalDAO(getConnectionSource(), Goal.class); } return goalDao; } /  RoleDAO public RoleDAO getRoleDAO() throws SQLException{ if(roleDao == null){ roleDao = new RoleDAO(getConnectionSource(), Role.class); } return roleDao; } //    @Override public void close(){ super.close(); goalDao = null; roleDao = null; } }
      
      







この例でわかるように、フィールドとテーブルの作成を記述し、DAOオブジェクトを含むシングルトンへのリンクの受信を実装する必要があります。 次に、DAO自体を直接見てみましょう。



DAO



最も単純な実装は次のクラスです



 public class RoleDAO extends BaseDaoImpl<Role, Integer>{ protected RoleDAO(ConnectionSource connectionSource, Class<Role> dataClass) throws SQLException{ super(connectionSource, dataClass); } public List<Role> getAllRoles() throws SQLException{ return this.queryForAll(); } }
      
      







ここでは、Roleクラスのすべてのオブジェクトのコレクションを取得するための追加メソッドを1つだけ作成しました。

メインメソッドcreate、update、deleteは、BaseDaoImplの祖先に実装されています。

任意のアプリケーションクラスのRoleDaoクラスのメソッドにアクセスするには、ファクトリクラスを使用するだけです。

RoleDAO roleDao = HelperFactory.GetHelper().getRoleDAO();







クエリを作成する



特定のクエリを作成するには、DAOクラスで独自のメソッドを作成できます。



 public List<Goal> getGoalByName(String name) throws SQLException{ QueryBuilder<Goal, String> queryBuilder = queryBuilder(); queryBuilder.where().eq(Goal.GOAL_NAME_FIELD_NAME, "First goal"); PreparedQuery<Goal> preparedQuery = queryBuilder.prepare(); List<Goal> goalList =query(preparedQuery); return goalList; }
      
      







ご覧のとおり、対応する名前フィールドを持つオブジェクトの検索がありました。

より複雑なクエリを作成する場合、 eq



(等しいことを意味する)に加えて、 gt



(より大きい)、 ge



(より大きいおよび等しい)、およびSQLの標準のwhere-constructionsに対応する残りの部分があります(完全なリストはこちら

複雑なクエリを作成するには、次を追加and



ます。

queryBuilder.where().eq(Goal.GOAL_NAME_FIELD_NAME, "First goal").and().eq(Goal.GOAL_NOTES_NAME_FIELD_NAME,”aaa”);







したがって、データベースからのクエリに加えて、同様の方法でテーブル削除および更新できます。



ネストされたエンティティを操作する





多対1の関係を検討してください。 目標オブジェクトに役割を指すフィールドがあるとします。

したがって、Goalクラスでは、フィールドに注釈を付ける必要があります。

 @DatabaseField(foreign = true) private Role role; public void setRole(Role value){ this.role = value; } public Role getRole(){ return role; }
      
      







これで、オブジェクトをデータベースに保存できます



  Goal g = new Goal(); g.setName(“asd”); Role r = new Role(); g.setRole(r); HelperFactory.getHelper.getRoleDAO().create(r); HelperFactory.getHelper.getGoalDAO().create(g);
      
      







タイプGoalのオブジェクトに関連付けられているRoleクラスのオブジェクトにアクセスするには:



  Goal g = HelperFactory.getHelper.getRoleDAO().getGoalByName(“asd”); Role r = g.getRole(); HelperFactory.getHelper.getRolelDAO().refresh(g);
      
      







refresh()



は、rがこのオブジェクトに対応するデータベースからすべてのフィールドを受け取るように実行する必要があります。



コレクション参照を保存する場合、アプローチはわずかに異なります。



目標クラス:



  @ForeignCollectionField(eager = true) private Collection<Role> roleList; public addRole(Role value){ value.setGoal(this); HelperFactory.GetHelper().getRoleDAO().create(value); roleList.add(value); } public void removeRole(Role value){ roleList.remove(value); HelperFactory.GetHelper().getRoleDAO().delete(value); }
      
      







eager



注釈の引数は、goalタイプのオブジェクトの抽出とともに、roleListのすべてのオブジェクトがデータベースから取得されることを意味します。 必須は、RoleオブジェクトのGoalへの参照です。 また、RoleDAOを使用して各Roleオブジェクトを個別に保存する必要もあります。

したがって、Roleクラスには注釈が必要です。



  @DatabaseField(foreign = true, foreignAutoRefresh = true) private Goal goal;
      
      







eager=true



設定しない場合、遅延初期化が実行されます。 Goalオブジェクトが要求されると、対応するroleListコレクションのオブジェクトは取得されません。 それらを抽出するには、それらを反復する必要があります。



  Iterator<Role> iter = state.goal.getRoleList().iterator(); while (iter.hasNext()) { Role r = iter.next(); }
      
      







ライブラリーへのリンク

チュートリアルへのリンク



All Articles