初心者にとっては、一歩後退して、ORMの一般的な内容を伝える価値があります。 ORM-オブジェクトとリレーショナルのマッピング。 オブジェクトリレーショナルマッピングは、 リレーショナルデータベースにデータを格納するテーブルよりも、アプリケーションで使用するオブジェクトを操作する方がプログラマにとってはるかに便利であることを意味します 。 ORMテクノロジーは、リレーショナルDBMSをアプリケーションオブジェクトモデルに接続するために使用されます。 したがって、Androidのオブジェクトリレーショナルマッピングの問題を解決するには、サードパーティのフレームワークのいずれかを使用します。 GreenDAOとORMLiteはオープンソースのライブラリです。
グリーンダオ
アプリケーションで使用するドイツの開発者によるフレームワーク。
利点:
Reflectionを使用して動作しません
Android ORMの最大パフォーマンス
最小限のメモリ使用量
ライブラリのサイズが小さいことは、Androidプロジェクトに大きな影響を与えません。
短所:
- スキーマを更新するときにデータを転送するメカニズムはありません。
- クラスに注釈を付けることは不可能であり、新しいエンティティを構築するためのアルゴリズムを記述する必要がある。
ORMLite
Androidに適合したバージョンを備えた人気のあるJavaフレームワーク。
利点:
- 強力かつシンプルな注釈
- 豊富な機能
- を含む多くのデータベースのサポート Sqlite
- KISS準拠のアーキテクチャ
短所:
...うーん...私はそれらを見つけませんでした)不可能と思われるすべては、ドックのより深い研究で実現されます。
私はいくつかのプロジェクトで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(); }
ライブラリーへのリンク 。
チュートリアルへのリンク 。