これを1回行う必要がある場合はすべて問題ありませんが、アプリケーションの開発時には、多くの場合データベースを変更する必要があります。
そして、それが複数のクラスにまたがると、列の追加/削除、型の変更などを忘れた場所で問題が発生します。 また、「ヘルプ」をコピーして貼り付けます:列を追加しました-コンマを入力するのを忘れていました。
これらの問題を解決するために、このライブラリが発明されました。
AnnotatedSQLは、注釈データベースを作成するためのコードを生成するライブラリです。 注釈はruntimeではありませんが、コンパイル時にプリプロセッサによって処理されます。 したがって、プロジェクトと最終apkには影響しません。
実際には、libは2つの部分で構成されています:注釈付きのjarとプリプロセッサ。
プロジェクトのlibsフォルダーに注釈を配置します。
プリプロセッサの使用は、IDEとプロジェクトのビルド方法に依存します。
Eclipseを使用する場合は、プラグインをプラグインフォルダーにコピーし、必要に応じてEclipseを再起動します。 次に、 Javaコンパイラ->注釈処理プロジェクトの設定に移動し、そこでコードを生成するフォルダーを選択します。 明らかに、標準のgenフォルダーを配置する必要があります。 次に、 Factory Pathに移動してプラグインを選択します。 それだけです。
IDEAの場合、プラグインは収集しませんでした。
antで使用するために、クラスパスにプリプロセッサを追加するだけで、次のようにします。
ant clean release -cp ../com.annotatedsql.AnnotatedSQL_1.0.12.jar
使用する
さらに技術的なことに移りましょう。 だから私たちはライブラリを接続する方法を知っていますが、それは何をしますか?
既に述べたように、アノテーションからデータベースを生成するか、データベースを生成するためにクラスを作成します。
いつものように、コードで使用するために、プレートの名前をテーブルとその列のインターフェースとして説明します。
たとえば、スポーツ大会の結果に関するデータを表示するアプリケーションがあります。 今のところサッカーの試合に参加してください。
明らかに、データベースにはいくつかのタグが必要です。 これはチーム、結果、そしてチャンピオンシップです。それらについて説明します。
通常、1つのクラス内のすべてのインターフェイスについて説明します。たとえば、FStoreと呼びましょう。 タブレットの説明に加えて、データベースの名前、そのバージョン、およびいくつかのユーティリティメソッドが含まれています。
public class FStore { public static final String DB_NAME = "fmanager"; public static final int DB_VERSION = 34; .......... public static interface TeamTable{ String TABLE_NAME = "team_table"; String ID = "_id"; String TITLE = "title"; String CHEMP_ID = "chemp_id"; String IS_FAV = "is_fav"; } public static interface ChempTable{ String TABLE_NAME = "chemp_table"; String CONTENT_PATH = "chemps"; String ID = "_id"; String TITLE = "title"; } public static interface ResultsTable{ String CONTENT_PATH = "results"; String PATH_VIEW = "results_view"; String TABLE_NAME = "result_table"; String ID = "_id"; String TEAM_ID = "team_id"; String POINTS = "points"; String CHEMP_ID = "chemp_id"; String GAMES = "games"; String WINS = "wins"; String TIE = "tie"; String LOSE = "lose"; String BALLS = "balls"; String GOALS = "goals"; } ........ }
CONTENT_PATHおよびあらゆる種類のPATH_VIEWに注意を払っていませんが。 これらは、コンテンツプロバイダーにアクセスするための定数です。
したがって、回路を作成するための手作業の量を示します。
さらに、読み取り可能な形式で結果を取得するには、プレートを相互に結合する必要があります。 これはコンテンツプロバイダーで行うことができますが、ここではViewを使用することを好みます。これは、書き込み用の別の大きなsqlピースです。
作業を容易にするために、このlibが作成されました。 それでは始めましょう。
スキーマ
FStore-注釈スキーマ( "SqlSchema")でマークし、コードを含むクラスの名前を設定します。 クラスは、FStoreが存在するのと同じパッケージで生成されます
@Schema("SqlSchema") public class FStore {
テーブル、インデックス、PrimaryKey
ラベルの説明にはテーブル注釈が設定され、テーブル名が設定されます
@Table(ChempTable.TABLE_NAME) public static interface ChempTable{ ................ @Table(TeamTable.TABLE_NAME) public static interface TeamTable{ ............... @Table(ResultsTable.TABLE_NAME) @Index(name = "chemp_index", columns = ResultsTable.CHEMP_ID) @PrimaryKey(collumns = {ResultsTable.TEAM_ID, ResultsTable.CHEMP_ID}) public static interface ResultsTable{
表にあるように、インデックスの作成と複雑なキーをハングさせることができます。 すべてが単純なようで、説明は必要ありません。
列、PrimaryKey、Autoincrement、NotNull
これらの注釈はフィールド用であり、使用するのも明らかです。
@Table(TeamTable.TABLE_NAME) public static interface TeamTable{ String TABLE_NAME = "team_table"; @PrimaryKey @Column(type = Type.INTEGER) String ID = "_id"; @NotNull @Column(type = Type.TEXT) String TITLE = "title"; @Column(type = Type.INTEGER) @NotNull String CHEMP_ID = "chemp_id"; @Column(type = Type.INTEGER, defVal="0") String IS_FAV = "is_fav"; }
シンプルビュー
そして、システムの最後の、非常に重要な要素であり、さほど重要ではない要素はSimpleViewです。
シンプルなビューを作成するための基本的な機能を提供します。 内部結合はまだありますが、他のものを追加します。
@SimpleView(ResultView.VIEW_NAME) public static interface ResultView{ String VIEW_NAME = "result_view"; @From(ResultsTable.TABLE_NAME) String TABLE_RESULT = "table_result"; @Join(srcTable = TeamTable.TABLE_NAME, srcColumn = TeamTable.ID, destTable = ResultView.TABLE_RESULT, destColumn = ResultsTable.TEAM_ID) String TABLE_TEAM = "table_team"; @Join(srcTable = ChempTable.TABLE_NAME, srcColumn = ChempTable.ID, destTable = ResultView.TABLE_RESULT, destColumn = ResultsTable.CHEMP_ID) String TABLE_CHEMP = "table_chemp"; }
ビュー内の注釈を検討してください。
From-これは私たちがするタブレットです:)重要-さらに、参加するときは、テーブル名ではなく、この定数を使用する必要があります。
結合 -実際には結合のテーブル。 私たちの場合、チームとチャンピオンシップのテーブルに参加する必要があります。
srcTableはソーステーブルです。
destTableは、ビューのfrom / joinテーブルの新しい名前です。 私たちの場合
String TABLE_RESULT = "table_result";
別の非常に重要なポイント -ビューでは、フィールド名は次のパターンに従って生成されます。
<variable_name>_<column_name>
例外は、アダプタのカーソルを使用するFromテーブルの_idフィールドです。
したがって、列インデックスを見つけるには、次のようなものを使用する必要があります
columnPoints = cursor.getColumnIndex(ResultView.TABLE_RESULT + "_" + ResultsTable.POINTS);
少し不快ですが、これは1回ごとに行われます
public void changeCursor(Cursor cursor) {
あなたはまだそのようなヘルパーを使用することができます
public class ColumnMappingHelper { private HashMap<String, HashMap<String, Integer>> indexes = new HashMap<String, HashMap<String, Integer>>(); public int getColumn(Cursor c, String table, String column){ HashMap<String, Integer> columns = indexes.get(table); if(columns != null){ Integer index = columns.get(column); if(index != null) return index; } if(columns == null){ columns = new HashMap<String, Integer>(); indexes.put(table, columns); } int index = c.getColumnIndex(table + "_" + column); columns.put(column, index); return index; } }
そしてそのように使用します
mappingHelper.getColumn(cursor, ResultView.TABLE_RESULT, ResultsTable.POINTS);
結果
生成されたファイルSqlSchema.java
public class SqlSchema{ private static final String SQL_CREATE_RESULT_TABLE = "create table result_table( balls INTEGER, chemp_id INTEGER NOT NULL, games INTEGER NOT NULL, goals INTEGER, _id INTEGER, lose INTEGER, points INTEGER NOT NULL, team_id INTEGER NOT NULL, tie INTEGER, wins INTEGER, PRIMARY KEY( team_id, chemp_id))"; private static final String SQL_CREATE_CHEMP_TABLE = "create table chemp_table( _id INTEGER PRIMARY KEY, title TEXT)"; private static final String SQL_CREATE_TEAM_TABLE = "create table team_table( chemp_id INTEGER NOT NULL, _id INTEGER PRIMARY KEY, is_fav INTEGER DEFAULT (0), title TEXT NOT NULL)"; private static final String SQL_CREATE_CHEMP_INDEX = "create index idx_chemp_index on result_table( chemp_id)"; private static final String SQL_CREATE_RESULT_VIEW = "CREATE VIEW result_view AS SELECT table_chemp._id as table_chemp__id, table_chemp.title as table_chemp_title, table_result.balls as table_result_balls, table_result.chemp_id as table_result_chemp_id, table_result.games as table_result_games, table_result.goals as table_result_goals, table_result._id, table_result.lose as table_result_lose, table_result.points as table_result_points, table_result.team_id as table_result_team_id, table_result.tie as table_result_tie, table_result.wins as table_result_wins, table_team.chemp_id as table_team_chemp_id, table_team._id as table_team__id, table_team.is_fav as table_team_is_fav, table_team.title as table_team_title FROM result_table AS table_result JOIN chemp_table AS table_chemp ON table_chemp._id = table_result.chemp_id JOIN team_table AS table_team ON table_team._id = table_result.team_id"; public static void onCreate(final SQLiteDatabase db) { db.execSQL(SQL_CREATE_RESULT_TABLE); db.execSQL(SQL_CREATE_CHEMP_TABLE); db.execSQL(SQL_CREATE_TEAM_TABLE); db.execSQL(SQL_CREATE_SCORE_TABLE); db.execSQL(SQL_CREATE_CHEMP_INDEX); db.execSQL(SQL_CREATE_RESULT_VIEW); db.execSQL(SQL_CREATE_SCORE_VIEW); } public static void onDrop(final SQLiteDatabase db){ db.execSQL("drop table if exists result_table"); db.execSQL("drop table if exists chemp_table"); db.execSQL("drop table if exists team_table"); db.execSQL("drop table if exists score_table"); db.execSQL("drop view if exists result_view"); db.execSQL("drop view if exists score_view"); } }
VIEWのresult_viewにtable_chemp_titleとしてtable_chemp__id、table_chemp.titleとしてAS SELECT table_chemp._idを、table_result_ballsなどtable_result.ballsは、table_result.games table_result_gamesとして、table_result.goals table_result_goalsとして、table_result、table_result_chemp_idとしてtable_result.chemp_id。 public class SqlSchema{ private static final String SQL_CREATE_RESULT_TABLE = "create table result_table( balls INTEGER, chemp_id INTEGER NOT NULL, games INTEGER NOT NULL, goals INTEGER, _id INTEGER, lose INTEGER, points INTEGER NOT NULL, team_id INTEGER NOT NULL, tie INTEGER, wins INTEGER, PRIMARY KEY( team_id, chemp_id))"; private static final String SQL_CREATE_CHEMP_TABLE = "create table chemp_table( _id INTEGER PRIMARY KEY, title TEXT)"; private static final String SQL_CREATE_TEAM_TABLE = "create table team_table( chemp_id INTEGER NOT NULL, _id INTEGER PRIMARY KEY, is_fav INTEGER DEFAULT (0), title TEXT NOT NULL)"; private static final String SQL_CREATE_CHEMP_INDEX = "create index idx_chemp_index on result_table( chemp_id)"; private static final String SQL_CREATE_RESULT_VIEW = "CREATE VIEW result_view AS SELECT table_chemp._id as table_chemp__id, table_chemp.title as table_chemp_title, table_result.balls as table_result_balls, table_result.chemp_id as table_result_chemp_id, table_result.games as table_result_games, table_result.goals as table_result_goals, table_result._id, table_result.lose as table_result_lose, table_result.points as table_result_points, table_result.team_id as table_result_team_id, table_result.tie as table_result_tie, table_result.wins as table_result_wins, table_team.chemp_id as table_team_chemp_id, table_team._id as table_team__id, table_team.is_fav as table_team_is_fav, table_team.title as table_team_title FROM result_table AS table_result JOIN chemp_table AS table_chemp ON table_chemp._id = table_result.chemp_id JOIN team_table AS table_team ON table_team._id = table_result.team_id"; public static void onCreate(final SQLiteDatabase db) { db.execSQL(SQL_CREATE_RESULT_TABLE); db.execSQL(SQL_CREATE_CHEMP_TABLE); db.execSQL(SQL_CREATE_TEAM_TABLE); db.execSQL(SQL_CREATE_SCORE_TABLE); db.execSQL(SQL_CREATE_CHEMP_INDEX); db.execSQL(SQL_CREATE_RESULT_VIEW); db.execSQL(SQL_CREATE_SCORE_VIEW); } public static void onDrop(final SQLiteDatabase db){ db.execSQL("drop table if exists result_table"); db.execSQL("drop table if exists chemp_table"); db.execSQL("drop table if exists team_table"); db.execSQL("drop table if exists score_table"); db.execSQL("drop view if exists result_view"); db.execSQL("drop view if exists score_view"); } }
、table_result_pointsは、table_team_chemp_idとしてtable_team.chemp_id、table_result.wins table_result_winsとして、table_result_tieとして、table_result_team_idとしてtable_result.tieをtable_result.team_id table_team_is_favとして、table_team__idとしてtable_team.is_favをtable_team._id public class SqlSchema{ private static final String SQL_CREATE_RESULT_TABLE = "create table result_table( balls INTEGER, chemp_id INTEGER NOT NULL, games INTEGER NOT NULL, goals INTEGER, _id INTEGER, lose INTEGER, points INTEGER NOT NULL, team_id INTEGER NOT NULL, tie INTEGER, wins INTEGER, PRIMARY KEY( team_id, chemp_id))"; private static final String SQL_CREATE_CHEMP_TABLE = "create table chemp_table( _id INTEGER PRIMARY KEY, title TEXT)"; private static final String SQL_CREATE_TEAM_TABLE = "create table team_table( chemp_id INTEGER NOT NULL, _id INTEGER PRIMARY KEY, is_fav INTEGER DEFAULT (0), title TEXT NOT NULL)"; private static final String SQL_CREATE_CHEMP_INDEX = "create index idx_chemp_index on result_table( chemp_id)"; private static final String SQL_CREATE_RESULT_VIEW = "CREATE VIEW result_view AS SELECT table_chemp._id as table_chemp__id, table_chemp.title as table_chemp_title, table_result.balls as table_result_balls, table_result.chemp_id as table_result_chemp_id, table_result.games as table_result_games, table_result.goals as table_result_goals, table_result._id, table_result.lose as table_result_lose, table_result.points as table_result_points, table_result.team_id as table_result_team_id, table_result.tie as table_result_tie, table_result.wins as table_result_wins, table_team.chemp_id as table_team_chemp_id, table_team._id as table_team__id, table_team.is_fav as table_team_is_fav, table_team.title as table_team_title FROM result_table AS table_result JOIN chemp_table AS table_chemp ON table_chemp._id = table_result.chemp_id JOIN team_table AS table_team ON table_team._id = table_result.team_id"; public static void onCreate(final SQLiteDatabase db) { db.execSQL(SQL_CREATE_RESULT_TABLE); db.execSQL(SQL_CREATE_CHEMP_TABLE); db.execSQL(SQL_CREATE_TEAM_TABLE); db.execSQL(SQL_CREATE_SCORE_TABLE); db.execSQL(SQL_CREATE_CHEMP_INDEX); db.execSQL(SQL_CREATE_RESULT_VIEW); db.execSQL(SQL_CREATE_SCORE_VIEW); } public static void onDrop(final SQLiteDatabase db){ db.execSQL("drop table if exists result_table"); db.execSQL("drop table if exists chemp_table"); db.execSQL("drop table if exists team_table"); db.execSQL("drop table if exists score_table"); db.execSQL("drop view if exists result_view"); db.execSQL("drop view if exists score_view"); } }
プレートの説明から定数を使用する必要はありません。 ファイルが生成され、テーブル宣言で記述した内容に明確に準拠します
SqlSchemaの使用
private class AnnotationSql extends SQLiteOpenHelper { public AnnotationSql(Context context) { super(context, FStore.DB_NAME, null, FStore.DB_VERSION); } @Override public void onCreate(SQLiteDatabase db) { SqlSchema.onCreate(db); init(db); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { SqlSchema.onDrop(db); onCreate(db); } }
計画
1.さまざまな種類の結合を追加する
2.結合に列注釈を追加して、必要なフィールドのみをレーキします
参照資料
バイナリ: github.com/hamsterksu/Android-AnnotatedSQL-binaries
ソース: github.com/hamsterksu/Android-AnnotatedSQL
ライセンス:MIT
みんなありがとう!
更新#1 :スキーマの更新について
私はOpenHelperを生成しません。自分で作成します。 複雑なロジックを書くことを誰も気にすることなく、生成されたスクリプトはonCreateで動作します 。
onUpgradeでは、フィールドの追加/削除/変更を非常に簡単に記述できます。テーブルとフィールドの名前があります。
図では、メンバーを開いてから、メンバーにアクセスし、テーブルを変更した後、ビューを再作成します。