Dialect
複数のDBを対象とするアプリケーションを作成する場合、DB毎のSQL文法の差異を吸収するため アプリケーションで対象DBを判定し実行するSQLファイルを切り替える、といった対応が必要になります。 uroboroSQLでは、こういったDB毎のSQL文法の差異に対応するため、Dialectという仕組みを提供しています。Dialectは接続したDBから取得できる情報を元に自動で判別される為、通常は変更する必要はありません。
現在、標準で以下のDBに対するDialectが提供されています。
| DB名 | Dialect |
|---|---|
| H2 DB | H2Dialect |
| Microsoft SQL Server | MsSqlDialect |
| MySQL | MySqlDialect |
| Oracle10g以下 | Oracle10Dialect |
| Oracle11g | Oracle11Dialect |
| Oracle12c以上 | Oracle12Dialect |
| Postgresql | PostgresqlDialect |
| その他 | DefaultDialect |
WARNING
該当するDBが見つからない場合はDefaultDialectが適用されます
カスタムDialectの登録
標準でサポートしている上記のDB以外に接続し、DefaultDialectと違う動作をさせたい場合は、対象のDBに対するDialectクラスを作成してuroboroSQLに登録する必要があります。
Dialectの登録には、Javaの java.util.ServiceLoaderを利用します。
最初に対象のDB(ここではSQLiteとする)に対するDialectクラスを作成します。
package foo.bar.dialect;
public class SqliteDialect extends AbstractDialect {
/**
* コンストラクタ
*/
public SqliteDialect() {
super();
}
@Override
public String getDatabaseName() {
return "SQLite"; // 対象DBの製品名を特定するための文字列を返す
}
// supportsXXXメソッド、isXXXメソッド、getXXXメソッドを必要に応じて実装
}Dialectインタフェースで提供すべきメソッドは以下になります。
| メソッド名 | 戻り値 | 説明 |
|---|---|---|
| supportsBulkInsert() | boolean | BULK INSERTをサポートするかどうか |
| supportsLimitClause() | boolean | LIMIT句をサポートするかどうか |
| supportsOptimizerHints() 0.18.0+ | boolean | オプティマイザーヒントをサポートするかどうか |
| supportsNullValuesOrdering() | boolean | SELECT句のORDER BYでNULL値の順序を指定できるか(NULLS FIRST/LAST) |
| supportsIdentity() | boolean | データベースのIDカラムを使用したID自動採番をサポートしているか |
| supportsSequence() | boolean | データベースのシーケンスを使用したID自動採番をサポートしているか |
| supportsForUpdate() | boolean | 明示的な行ロックをサポートしているか |
| supportsForUpdateNoWait() | boolean | 明示的な行ロック(待機なし)をサポートしているか |
| supportsForUpdateWait() | boolean | 明示的な行ロック(待機あり)をサポートしているか |
| isRemoveTerminator() | boolean | 実行するSQLに記述されている終端文字(;)を削除するかどうか |
| isRollbackToSavepointBeforeRetry() | boolean | リトライする前に設定したSavepointまでロールバックするかどうか |
| getSequenceNextValSql(String sequenceName) | String | シーケンスを取得するためのSQL文を取得する |
| getLimitClause(long limit, long offset) | String | LIMIT句(とOFFSET句)を取得する |
| escapeLikePattern(CharSequence pattern) | String | LIKE演算子のパターン文字列をエスケープする |
| getJavaType(JDBCType jdbcType, String jdbcTypeName) | JavaType | 引数で渡ってきたJavaTypeを変換したJavaTypeを取得する。(DB固有のJava型変換を行う場合に実装) |
| getJavaType(int jdbcType, String jdbcTypeName) | JavaType | 引数で渡ってきたJavaTypeを変換したJavaTypeを取得する。(DB固有のJava型変換を行う場合に実装) |
| getDatabaseName() | String | データベースを判別するための文字列を取得する |
| getDatabaseType() | String | データベースの種別を表す名前を取得する |
| getEscapeChar() | char | LIKE句で指定するエスケープキャラクタを取得する |
| addForUpdateClause(StringBuilder sql, ForUpdateType forUpdateType, int waitSeconds) | StringBuilder | FOR UPDATE句の文字列をSQLに追加する |
| addOptimizerHints(StringBuilder sql, List<String> hints) 0.18.0+ | StringBuilder | 引数で渡したSQLにオプティマイザーヒントを付与する |
| getModLiteral(final String dividend, final String divisor) 0.17.0+ | StringBuilder | 乗除を行うためのSQL文字列を取得する |
| getPessimisticLockingErrorCodes() 0.18.2+ | Set<String> | 悲観ロックのErrorCode もしくは SqlStateを取得する |
Dialectインタフェースのデフォルト実装やAbstractDialectクラスを参考に、上記のメソッドのうち変更が必要なメソッドの実装を行ってください。
次にuroboroSQLを利用するアプリケーションのクラスパス上に以下のファイル名のファイルを作成します。
META-INF
└─services
└─jp.co.future.uroborosql.dialect.Dialect最後に作成したjp.co.future.uroborosql.dialect.Dialectファイルの中に作成したDialectのクラス名(FQDN名)を記述します。
foo.bar.dialect.SqliteDialectアプリケーションでjp.co.future.uroborosql.dialect.DialectがServiceLoader経由で読み込まれれば登録したSqliteDialectが利用可能になります。
