001/* 002 * Copyright (c) 2022-2023, Mybatis-Flex (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package com.mybatisflex.core.dialect; 017 018 019import com.mybatisflex.core.FlexGlobalConfig; 020import com.mybatisflex.core.dialect.impl.CommonsDialectImpl; 021import com.mybatisflex.core.dialect.impl.OracleDialect; 022import com.mybatisflex.core.util.ObjectUtil; 023import org.apache.ibatis.util.MapUtil; 024 025import java.util.EnumMap; 026import java.util.Map; 027 028/** 029 * 方言工厂类,用于创建方言 030 */ 031public class DialectFactory { 032 033 private DialectFactory() {} 034 035 /** 036 * 数据库类型和方言的映射关系,可以通过其读取指定的方言,亦可能通过其扩展其他方言 037 * 比如,在 mybatis-flex 实现的方言中有 bug 或者 有自己的独立实现,可以添加自己的方言实现到 038 * 此 map 中,用于覆盖系统的方言实现 039 */ 040 private static final Map<DbType, IDialect> dialectMap = new EnumMap<>(DbType.class); 041 042 /** 043 * 通过设置当前线程的数据库类型,以达到在代码执行时随时切换方言的功能 044 */ 045 private static final ThreadLocal<DbType> dbTypeThreadLocal = new ThreadLocal<>(); 046 047 048 /** 049 * 获取方言 050 * 051 * @return IDialect 052 */ 053 public static IDialect getDialect() { 054 DbType dbType = ObjectUtil.requireNonNullElse(dbTypeThreadLocal.get(), FlexGlobalConfig.getDefaultConfig().getDbType()); 055 return MapUtil.computeIfAbsent(dialectMap, dbType, DialectFactory::createDialect); 056 } 057 058 /** 059 * 设置当前线程的 dbType 060 * 061 * @param dbType 062 */ 063 public static void setHintDbType(DbType dbType) { 064 dbTypeThreadLocal.set(dbType); 065 } 066 067 /** 068 * 获取当前线程的 dbType 069 * 070 * @return dbType 071 */ 072 public static DbType getHintDbType() { 073 return dbTypeThreadLocal.get(); 074 } 075 076 077 /** 078 * 清除当前线程的 dbType 079 */ 080 public static void clearHintDbType() { 081 dbTypeThreadLocal.remove(); 082 } 083 084 085 /** 086 * 可以为某个 dbType 注册(新增或覆盖)自己的方言 087 * 088 * @param dbType 数据库类型 089 * @param dialect 方言的实现 090 */ 091 public static void registerDialect(DbType dbType, IDialect dialect) { 092 dialectMap.put(dbType, dialect); 093 } 094 095 096 private static IDialect createDialect(DbType dbType) { 097 switch (dbType) { 098 case MYSQL: 099 case H2: 100 case MARIADB: 101 case GBASE: 102 case OSCAR: 103 case XUGU: 104 case CLICK_HOUSE: 105 case OCEAN_BASE: 106 case CUBRID: 107 case GOLDILOCKS: 108 case CSIIDB: 109 return new CommonsDialectImpl(KeywordWrap.BACKQUOTE, LimitOffsetProcessor.MYSQL); 110 case ORACLE: 111 return new OracleDialect(); 112 case DM: 113 case GAUSS: 114 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.ORACLE); 115 case POSTGRE_SQL: 116 case SQLITE: 117 case HSQL: 118 case KINGBASE_ES: 119 case PHOENIX: 120 case SAP_HANA: 121 case IMPALA: 122 case HIGH_GO: 123 case VERTICA: 124 case REDSHIFT: 125 case OPENGAUSS: 126 case UXDB: 127 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.POSTGRESQL); 128 case TDENGINE: 129 return new CommonsDialectImpl(KeywordWrap.BACKQUOTE, LimitOffsetProcessor.POSTGRESQL); 130 case ORACLE_12C: 131 return new OracleDialect(LimitOffsetProcessor.DERBY); 132 case FIREBIRD: 133 case DB2: 134 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.DERBY); 135 case SQLSERVER: 136 return new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER); 137 case INFORMIX: 138 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.INFORMIX); 139 case SYBASE: 140 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.SYBASE); 141 default: 142 return new CommonsDialectImpl(); 143 } 144 } 145}