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 java.util.EnumMap; 020import java.util.Map; 021import org.apache.ibatis.util.MapUtil; 022import com.mybatisflex.core.FlexGlobalConfig; 023import com.mybatisflex.core.dialect.impl.CommonsDialectImpl; 024import com.mybatisflex.core.dialect.impl.DB2105Dialect; 025import com.mybatisflex.core.dialect.impl.DmDialect; 026import com.mybatisflex.core.dialect.impl.OracleDialect; 027import com.mybatisflex.core.util.ObjectUtil; 028 029/** 030 * 方言工厂类,用于创建方言 031 */ 032public class DialectFactory { 033 034 private DialectFactory() { 035 } 036 037 /** 038 * 数据库类型和方言的映射关系,可以通过其读取指定的方言,亦可能通过其扩展其他方言 039 * 比如,在 mybatis-flex 实现的方言中有 bug 或者 有自己的独立实现,可以添加自己的方言实现到 040 * 此 map 中,用于覆盖系统的方言实现 041 */ 042 private static final Map<DbType, IDialect> dialectMap = new EnumMap<>(DbType.class); 043 044 /** 045 * 通过设置当前线程的数据库类型,以达到在代码执行时随时切换方言的功能 046 */ 047 private static final ThreadLocal<DbType> dbTypeThreadLocal = new ThreadLocal<>(); 048 049 050 /** 051 * 获取方言 052 * 053 * @return IDialect 054 */ 055 public static IDialect getDialect() { 056 DbType dbType = ObjectUtil.requireNonNullElse(dbTypeThreadLocal.get(), FlexGlobalConfig.getDefaultConfig().getDbType()); 057 return MapUtil.computeIfAbsent(dialectMap, dbType, DialectFactory::createDialect); 058 } 059 060 /** 061 * 设置当前线程的 dbType 062 * 063 * @param dbType 064 */ 065 public static void setHintDbType(DbType dbType) { 066 dbTypeThreadLocal.set(dbType); 067 } 068 069 /** 070 * 获取当前线程的 dbType 071 * 072 * @return dbType 073 */ 074 public static DbType getHintDbType() { 075 return dbTypeThreadLocal.get(); 076 } 077 078 079 /** 080 * 清除当前线程的 dbType 081 */ 082 public static void clearHintDbType() { 083 dbTypeThreadLocal.remove(); 084 } 085 086 087 /** 088 * 可以为某个 dbType 注册(新增或覆盖)自己的方言 089 * 090 * @param dbType 数据库类型 091 * @param dialect 方言的实现 092 */ 093 public static void registerDialect(DbType dbType, IDialect dialect) { 094 dialectMap.put(dbType, dialect); 095 } 096 097 098 private static IDialect createDialect(DbType dbType) { 099 switch (dbType) { 100 case MYSQL: 101 case H2: 102 case MARIADB: 103 case GBASE: 104 case OSCAR: 105 case XUGU: 106 case OCEAN_BASE: 107 case CUBRID: 108 case GOLDILOCKS: 109 case CSIIDB: 110 case HIVE: 111 case DORIS: 112 return new CommonsDialectImpl(KeywordWrap.BACK_QUOTE, LimitOffsetProcessor.MYSQL); 113 case CLICK_HOUSE: 114 case GBASE_8S: 115 return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.MYSQL); 116 case DM: 117 return new DmDialect(); 118 case ORACLE: 119 return new OracleDialect(); 120 case GAUSS: 121 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.ORACLE); 122 case POSTGRE_SQL: 123 case SQLITE: 124 case HSQL: 125 case KINGBASE_ES: 126 case PHOENIX: 127 case SAP_HANA: 128 case IMPALA: 129 case HIGH_GO: 130 case VERTICA: 131 case REDSHIFT: 132 case OPENGAUSS: 133 case UXDB: 134 case LEALONE: 135 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.POSTGRESQL); 136 case TDENGINE: 137 return new CommonsDialectImpl(KeywordWrap.BACK_QUOTE, LimitOffsetProcessor.POSTGRESQL); 138 case ORACLE_12C: 139 return new OracleDialect(LimitOffsetProcessor.DERBY); 140 case FIREBIRD: 141 case DB2: 142 return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.DERBY); 143 case DB2_1005: 144 return new DB2105Dialect(KeywordWrap.NONE, DB2105Dialect.DB2105LimitOffsetProcessor.DB2105); 145 case SQLSERVER: 146 return new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER); 147 case SQLSERVER_2005: 148 return new CommonsDialectImpl(KeywordWrap.SQUARE_BRACKETS, LimitOffsetProcessor.SQLSERVER_2005); 149 case INFORMIX: 150 return new CommonsDialectImpl(KeywordWrap.NONE, LimitOffsetProcessor.INFORMIX); 151 case SINODB: 152 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.SINODB); 153 case SYBASE: 154 return new CommonsDialectImpl(KeywordWrap.DOUBLE_QUOTATION, LimitOffsetProcessor.SYBASE); 155 default: 156 return new CommonsDialectImpl(); 157 } 158 } 159 160}