mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-14 20:25:26 +02:00
9.3 KiB
9.3 KiB
tinystruct データベース永続化
使用する場面
データベース操作にはフレームワーク組み込みのORM的なデータ層を使用します。これは AbstractData を拡張したPOJOを、アノテーションまたはXMLマッピングファイルでテーブルにマッピングし、JPA/Hibernateの軽量な代替として機能します。
動作の仕組み
アーキテクチャ
各テーブルは以下によって表されます:
- Java POJO:
AbstractDataを拡張し、getter/setter とsetData(Row)を提供する。 - マッピング、いずれか一方:
- アノテーション:クラスに
@Table、フィールドに@Column(アノテーションマッピングを参照)。 - マッピングXML:リソースに置かれた
ClassName.map.xmlで、Javaフィールドとデータベースカラムを結びつける。
- アノテーション:クラスに
マッピングはクラスごとに一度だけ読み込まれてキャッシュされるため、インスタンスの生成で再読み込みや再解析は行われません。クラスに @Table が存在する場合、同名の .map.xml より優先されます。
主要な基底クラス:AbstractData
CRUDメソッドを提供します:
append()/appendAndGetId()update()delete()findAll()/findOneById()/findOneByKey(key, value)findWith(where, params)find(SQL, params)
POJOの生成(CLI)
ライブのデータベーステーブルを内省してPOJOとそのマッピングを生成します。デフォルトでは .map.xml ファイルが、annotation オプションを指定するとPOJO自体にアノテーションが付与されます。
設定
application.properties:
driver=com.mysql.cj.jdbc.Driver
database.url=jdbc:mysql://localhost:3306/mydb
database.user=root
database.password=secret
コマンド
# インタラクティブモード
bin/dispatcher generate
# テーブルを指定
bin/dispatcher generate --tables users
# .map.xml ではなくPOJOにアノテーションを付与
bin/dispatcher generate --tables users --mapping annotation
--mapping は xml(デフォルト)または annotation を受け付けます。アノテーションモードでは .map.xml は書き出されず、リソースディレクトリも作成されません。不明な値を指定するとプロンプトの前にエラーで拒否されます。
例
CRUD操作
// CREATE
User user = new User();
user.setUsername("james");
user.append();
// READ
User user = new User();
user.setId(42);
user.findOneById();
// UPDATE
user.setEmail("new@example.com");
user.update();
// DELETE
user.delete();
条件を使ったクエリ
User user = new User();
Table results = user.findWith("username LIKE ?", new Object[]{"%jam%"});
// 流暢なConditionビルダー
Condition condition = new Condition();
condition.setRequestFields("id,username");
Table filtered = user.find(
condition.select("`users`").and("email LIKE ?").orderBy("id DESC"),
new Object[]{"%@example.com"}
);
マッピングXMLの構造
User.map.xml:
<mapping>
<class name="User" table="users">
<id name="Id" column="id" autoIncrement="true" autoGenerated="false" length="11" type="int"/>
<property name="username" column="username" length="50" type="varchar"/>
<property name="email" column="email" length="100" type="varchar"/>
</class>
</mapping>
アノテーションマッピング
アノテーションを使った同じ User(generate --mapping annotation が生成するもの):
import org.tinystruct.data.annotation.Column;
import org.tinystruct.data.annotation.Id;
import org.tinystruct.data.annotation.Table;
import org.tinystruct.data.component.AbstractData;
import java.io.Serializable;
@Table(name = "users",
id = @Id(name = "Id", column = "id", type = "int", length = 11, autoIncrement = true))
public class User extends AbstractData implements Serializable {
@Column(name = "username", type = "varchar", length = 50)
private String username;
@Column(name = "email", type = "varchar", length = 100)
private String email;
// getter、setter(setFieldAsXxx を使用)、および setData(Row) を通常通り実装
}
| アノテーション | 対象 | 属性 |
|---|---|---|
@Table |
クラス | name(必須)、schema(デフォルト:なし)、id(デフォルト:識別子なし) |
@Id |
@Table(id = ...) 内 |
name(デフォルト Id)、column、type、length、autoIncrement、autoGenerated。column が空の場合、テーブルに識別子がないことを意味する。 |
@Column |
フィールド | type(必須)、name(DBカラム名。デフォルトはJavaフィールド名)、length |
- 識別子は
AbstractDataから継承されるため、独自のフィールドに@Idでアノテーションするのではなく@Table内で記述する。 typeはXMLのtype属性と同じ名前(FieldTypeの名前、大文字小文字を無視してマッチング)を取る:INT、BIGINT、VARCHAR、TEXT、DATE、TIMESTAMPなど。@Columnが付与されたフィールドのみマッピングされる。@Tableは継承され、スーパークラスのアノテーション付きフィールドもマッピングされる。- 同じプロパティを二重にマッピング(例:スーパークラスのアノテーション付きフィールドを隠すサブクラスフィールド)すると、そのクラスが最初に使われる際にエラーになる。
autoGenerated = trueは整数でないIDに新規インスタンスごとにUUIDを付与し、autoIncrement = trueはその値をデータベースに委ねる。.map.xmlの<id>要素も同じ名前autoIncrement・autoGeneratedを使う。旧来のincrement・generate属性で書かれたファイルも引き続き動作する。両方の綴りが存在する場合、新しい方が優先される。
テーブルの自動作成
application.properties に1行追加することで、存在しないテーブルを自動的に作成できます:
database.autocreate=true
- デフォルトはオフ。 これをオンにしない限り、スキーマは何も変更されません。オンにする場合、データベースユーザーは
CREATE権限が必要です。 - マッピングされたクラスが最初にインスタンス化される際に、テーブルが存在しなければ作成されます。これはプロセスごと・クラスごとに一度だけ発生し、アノテーションとXMLマッピングの両方で機能し、以降のインスタンスには何も追加されません。
CREATE TABLE IF NOT EXISTSという単一ステートメントが使用され、複数のインスタンスが同時に起動しても安全です(SQL Server ではOBJECT_IDガードが使われます)。@Idカラムが主キーになり、autoIncrement = trueの場合はデータベース固有のオートインクリメントまたはIDENTITY構文が使われます。- カラム型はターゲットデータベース固有の型にレンダリングされます(例:
TIMESTAMPはMySQLではDATETIME、SQL ServerではDATETIME2、TEXTはSQL ServerではVARCHAR(MAX)、BLOBはPostgreSQLではBYTEA)。lengthなしのVARCHARは255になります。 - 失敗(例:権限不足)は警告としてログに記録され、オブジェクトの生成は停止しません。最初の実際のステートメントでデータベース固有のエラーが報告されます。
注意点:
DECIMALカラムはマッピングが単一のlengthのみを持つため、精度やスケールなしで作成されます。FieldTypeの名前に含まれないカラム型は拒否されます。- テーブル、カラム、主キーのみが作成されます。インデックス、外部キー、デフォルト値、他カラムへの
NOT NULLは作成されません。 - 既存のテーブルはマッピングと異なっていても変更・マイグレーションされません。
- Redisはテーブルを持たず、サポートされていません。
重要なルール
- ファイルの配置(XMLマッピングのみ):マッピングXMLは
src/main/resources/以下にPOJOのパッケージパスを反映した場所に置く必要があります。 - 命名規則:テーブル名はクラス名に単数化されます(
users→User)。アンダースコアのカラムはキャメルケースのフィールドになります(created_at→createdAt)。 - セッター:セッターでは(例:
setFieldAsString)setFieldAsXxxメソッドを使用して内部フィールドマップと状態を同期させてください。 - Idフィールド:Javaでの主キーフィールドは常に
Idという名前です(AbstractDataから継承)。 - マッピングソースは1つ:クラスに対してアノテーションかXMLのどちらかを使用してください。両方が存在する場合、アノテーションが優先されてXMLは無視されます。