SQLiteの取扱い

基本情報

対応バージョン
SQLite 3 以上
JDBCドライバの同梱
なし
(推奨)JDBCドライバ
sqlite-jdbc-3.6.20.x.jar (Exampleで利用)

DBFluteの SQLite 対応は、(正式サポートではない)準サポートです。

データベース接続設定

データベース接続設定(databaseInfoMap.dfprop)について。

接続設定の仕様 @databaseInfoMap.dfprop
map:{
    ; driver   = org.sqlite.JDBC
    ; url      = jdbc:sqlite:../src/main/resources/[...]/[dbname].db
    ; schema   = 
    ; user     = [dbuser]
    ; password = [dbpassword]
}
  • catalog はそもそも対応する概念がないため設定不要
  • schema はそもそも対応する概念がないため設定不要
  • [xxx]の[]は単なる表現上(ドキュメント上)の囲み

以下、実際のExampleプロジェクトでの設定例です。

e.g. dbflute-sqlite-exampleの場合 {dbname=exampledb} @databaseInfoMap.dfprop
map:{
    ; driver   = org.sqlite.JDBC
    ; url      = jdbc:sqlite:../src/main/resources/exampledb/exampledb.db
    ; schema   = 
    ; user     = sa
    ; password = 
}

データ型マッピング

データベース上のデータ型とプログラム型との(デフォルトの)マッピングについて。

java.lang.String
TEXT, DATE, DATETIME, (others...)
java.lang.Integer
INTEGER

任意のマッピング

ほとんどが String にマッピングされてしまうので、任意の型へのマッピングの調整をお奨めします。例えば、DATE や DATETIME を java.util.Date や java.sql.Timestamp に関連付けると扱いやすくなります。

現場フィット - NUMERICの自動マッピング

但し、逆に捉えるとほとんどの型が未サポートのデータ型とも言えますので、未サポートのデータ型に対する取扱いも必ず理解した上でご利用下さい。

主キーでの自動採番

自動採番(連番)の仕組みとして Identity を利用します。

Identity情報はメタデータから取得できるので、設定なしで利用可能です。

ページング検索の条件

limitoffset を利用します。

ConditionBeanのPaging

e.g. ConditionBeanでページング検索 {81-100} @DisplaySql
select ...
  from MEMBER dfloc  
 order by dfloc.MEMBER_NAME asc 
 offset 80 limit 20

OutsideSqlのManualPaging

e.g. OutsideSqlのManualPagingでページング検索 {81-100} @OutsideSql
/*IF pmb.isPaging()*/
select ...
-- ELSE select count(*)
/*END*/
  from ... 
 where ...
 /*IF pmb.isPaging()*/
 order by ... 
 offset /*$pmb.pageStartIndex*/80 limit /*$pmb.fetchSize*/20
 /*END*/
  • offset や limit ではバインド変数が利用できないので、埋め込み変数("$" を付与)を利用すること

更新ロックの取得

ConditionBean の lockForUpdate() では、for update を利用します。

e.g. ConditionBeanで更新ロックの取得 (cb.lockForUpdate()) @DisplaySql
select ...
  from MEMBER dfloc
 where ...
   and ...
 for update

プロシージャ

*未検証

データベース依存機能

データベース依存機能を有効にした場合の利用可能な機能について。

SQLiteに関しては特になし

DBMS独自の注意点

NullsFirst/Last

nulls first/last 構文をサポートしていないため、case when 構文を使って NullsFirst/Last を実現しています。union 句での case when 構文がサポートされないため、UnionQuery と NullsFirst/Last を合わせてることはできません。 (また、パフォーマンス上の懸念が多少あるので、大量データのときには注意して下さい)

ReplaceSchemaでFKのdrop処理の抑制

SQLite用のFK制約の drop 構文に対応できていないため、ReplaceSchema のFKのdrop処理にてエラーになります。FK制約があるままでもテーブルの drop ができることを利用し(*どういうことなのか未検証)、FKのdrop処理を抑制することでReplaceSchemaが利用できます。 replaceSchemaDefinitionMap.dfprop の isSuppressDropForeignKey を有効にすることでFKのdrop処理を抑制できます。

一意制約違反の例外が不明

SQLiteの一意制約違反の判定が不明のため(SQLStateは null だし、errorCodeは常に 0 だし)、EntityAlreadyExistsException によるハンドリングができません(他のエラーと同様にSQLFailureExceptionが発生)。

更新ロックができない

SQLiteの更新ロック(for update)の構文が不明のため、ConditionBeanの lockForUpdate() は利用できません(for updateが付与されますがエラーになります)。

Exampleのススメ

SQLite を使ったExample実装 dbflute-sqlite-example があります。

DBFlute Example - データベース

DBFlute内部での取扱い

DBFlute内部でどのようにSQLiteと付き合っているか、特殊なパターンを挙げます。 将来的に同じ状況・同じ方法かどうかは保証されませんので、ここに書かれることに依存した利用はしないようにして下さい。 (DBFluteを深く理解するためのドキュメントと思って下さい)

PreparedStatementのBigDecimalが未サポート
PreparedStatement の setBigDecimal() がサポートされていないため、ReplaceSchema でのデータ登録処理の中でより細かい型の判定をするようにしました。
sqlite_で始まるテーブルの(自動)除外
作成されたテーブルの構成次第で、自動で sqlite_ で始まる(システム)テーブルが作成され、そのままだと自動生成対象になってしまうため、DBFluteで明示的に(自動で)除外されるようにしました。

SQLite補足資料

Identity設定

PRIMARY KEY の後に AUTOINCREMENT を定義します。

e.g. Identity設定 {MEMBERのMEMBER_IDにIdentity} @DDL
create table MEMBER (
    MEMBER_ID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    MEMBER_NAME TEXT NOT NULL,
    ...
) ;

発行された連番を insert 実行後に取得

e.g. 発行された連番を insert 実行後に取得 @SQL
select last_insert_rowid()