Android SDKのDB操作を便利にしたい
AndroidのDB操作が不便です。(文字列ベースなのでEclipseの補完が使えない等)
通常の書き方(rawQueryの場合)
Cursor cursor = db.rawQuery("select * from employee where _id in (?, ?);", new String[] {"2", "3"}); List<Employee> list = new ArrayList<Employee>(); while(cursor.moveToNext()) { Employee emp = new Employee(); int id = cursor.getInt(cursor.getColumnIndex("_id")); String name = cursor.getString(cursor.getColumnIndex("name")); emp.setId(id); emp.setName(name); list.add(emp); }
流れるインタフェースで書きたい
Slim3やS2ContainerのORマッパーS2JDBCのような、流れるインターフェースで書けたら幸せ。
S2JDBCの流れるインターフェース
List<Employee> results = jdbcManager.from(Employee.class) .join("department") .where("id in (? , ?)", 11, 22) .orderBy("name") .getResultList();
SQLiteDatabaseのラッパークラス
public class SQLiteDatabaseWrapper { private SQLiteDatabase mDatabase; public SQLiteDatabaseWrapper(SQLiteDatabase writableDatabase) { mDatabase = writableDatabase; } public <M> AutoSelect<M> from(Class<M> fromClass) { return new AutoSelect<M>(fromClass, mDatabase); } //以下略
クエリを処理するAutoSelect
とりあえずwhereだけ実装。(joinとかorderbyとかは後回し)
public class AutoSelect<M> { private Class<M> fromClass; private SQLiteDatabase mDatabase; private String criteria; private String[] params; public AutoSelect(Class<M> fromClass, SQLiteDatabase mDatabase) { this.fromClass = fromClass; this.mDatabase = mDatabase; } public Cursor getCursor() { ModelMeta<M> meta = SQLiteDatabaseWrapper.getModelMeta(fromClass); return mDatabase.query(meta.getTableName(), null, criteria, params, null, null, null); } public int getCount() { return getCursor().getCount(); } public AutoSelect<M> where(String criteria, String... params) { this.criteria = criteria; this.params = params; return this; } public AutoSelect<M> where(String criteria, int... intParams) { params = new String[intParams.length]; for (int i = 0; i < intParams.length; i++) { params[i] = String.valueOf(intParams[i]); } this.criteria = criteria; return this; } public List<M> getResultList() { List<M> list = new ArrayList<M>(); Cursor cursor = getCursor(); while (cursor.moveToNext()) { ContentValues values = new ContentValues(); String[] columnNames = cursor.getColumnNames(); for (int i = 0; i < columnNames.length; i++) { String value = cursor.getString(cursor.getColumnIndex(columnNames[i])); values.put(columnNames[i], value); } ModelMeta<M> meta = SQLiteDatabaseWrapper.getModelMeta(fromClass); list.add(meta.contentValuesToModel(values)); } return list; } }
ModelMetaの実装クラス。
Slim3のModelMetaを参考にしました。(DatastoreのEntityを、ContentValuesで置き換えたイメージ)
public class EmployeeMeta extends ModelMeta<Employee> { @Override public String getTableName() { return "hoge"; } @Override public ContentValues modelToContentValues(Object model) { Employee emp = (Employee) model; ContentValues values = new ContentValues(); values.put("_id", emp.get_id()); values.put("name", emp.getName()); values.put("date", emp.getDate()); return values; } @Override public Employee contentValuesToModel(ContentValues values) { Employee emp = new Employee(); emp.setId(values.getAsInteger("_id")); emp.setName(values.getAsString("name")); emp.setDate(values.getAsString("date")); return emp; } }