# Dialect

複数のDBを対象とするアプリケーションを作成する場合、DB毎のSQL文法の差異を吸収するため アプリケーションで対象DBを判定し実行するSQLファイルを切り替える、といった対応が必要になります。 uroboroSQLでは、こういったDB毎のSQL文法の差異に対応するため、Dialectという仕組みを提供しています。
Dialectは接続したDBから取得できる情報を元に自動で判別される為、通常は変更する必要はありません。

現在、標準で以下のDBに対するDialectが提供されています。

DB名 Dialect
H2 DB H2Dialect (opens new window)
Microsoft SQL Server MsSqlDialect (opens new window)
MySQL MySqlDialect (opens new window)
Oracle10g以下 Oracle10Dialect (opens new window)
Oracle11g Oracle11Dialect (opens new window)
Oracle12c以上 Oracle12Dialect (opens new window)
Postgresql PostgresqlDialect (opens new window)
その他 DefaultDialect (opens new window)

WARNING

該当するDBが見つからない場合はDefaultDialectが適用されます

# カスタムDialectの登録

標準でサポートしている上記のDB以外に接続し、DefaultDialectと違う動作をさせたい場合は、対象のDBに対するDialectクラスを作成してuroboroSQLに登録する必要があります。

Dialectの登録には、Javaの java.util.ServiceLoader (opens new window)を利用します。

最初に対象の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メソッドを必要に応じて実装
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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
1
2
3

最後に作成したjp.co.future.uroborosql.dialect.Dialectファイルの中に作成したDialectのクラス名(FQDN名)を記述します。

foo.bar.dialect.SqliteDialect
1

アプリケーションでjp.co.future.uroborosql.dialect.DialectServiceLoader経由で読み込まれれば登録したSqliteDialectが利用可能になります。