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.provider; 017 018import com.mybatisflex.core.FlexConsts; 019import com.mybatisflex.core.dialect.DialectFactory; 020import com.mybatisflex.core.exception.FlexExceptions; 021import com.mybatisflex.core.query.CPI; 022import com.mybatisflex.core.query.QueryTable; 023import com.mybatisflex.core.query.QueryWrapper; 024import com.mybatisflex.core.table.TableInfo; 025import com.mybatisflex.core.table.TableInfoFactory; 026import com.mybatisflex.core.util.ArrayUtil; 027import com.mybatisflex.core.util.CollectionUtil; 028import com.mybatisflex.core.util.StringUtil; 029import org.apache.ibatis.builder.annotation.ProviderContext; 030 031import java.io.Serializable; 032import java.util.*; 033 034public class EntitySqlProvider { 035 036 /** 037 * 不让实例化,使用静态方法的模式,效率更高,非静态方法每次都会实例化当前类 038 * 参考源码: {{@link org.apache.ibatis.builder.annotation.ProviderSqlSource#getBoundSql(Object)} 039 */ 040 private EntitySqlProvider() { 041 } 042 043 044 /** 045 * insert 的 sql 构建 046 * 047 * @param params 048 * @param context 049 * @return sql 050 * @see com.mybatisflex.core.BaseMapper#insert(Object) 051 */ 052 public static String insert(Map params, ProviderContext context) { 053 Object entity = ProviderUtil.getEntity(params); 054 if (entity == null) { 055 throw FlexExceptions.wrap("entity can not be null."); 056 } 057 058 boolean ignoreNulls = ProviderUtil.isIgnoreNulls(params); 059 060 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 061 062 //设置乐观锁版本字段的初始化数据 063 tableInfo.initVersionValueIfNecessary(entity); 064 065 //设置租户ID 066 tableInfo.initTenantIdIfNecessary(entity); 067 068 //设置逻辑删除字段的出初始化数据 069 tableInfo.initLogicDeleteValueIfNecessary(entity); 070 071 //执行 onInsert 监听器 072 tableInfo.invokeOnInsertListener(entity); 073 074 Object[] values = tableInfo.buildInsertSqlArgs(entity, ignoreNulls); 075 ProviderUtil.setSqlArgs(params, values); 076 077 return DialectFactory.getDialect().forInsertEntity(tableInfo, entity, ignoreNulls); 078 } 079 080 081 /** 082 * insertBatch 的 sql 构建 083 * 084 * @param params 085 * @param context 086 * @return sql 087 * @see com.mybatisflex.core.BaseMapper#insertBatch(List) 088 * @see com.mybatisflex.core.FlexConsts#METHOD_INSERT_BATCH 089 */ 090 public static String insertBatch(Map params, ProviderContext context) { 091 List<Object> entities = ProviderUtil.getEntities(params); 092 if (CollectionUtil.isEmpty(entities)) { 093 throw FlexExceptions.wrap("entities can not be null or empty."); 094 } 095 096 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 097 for (Object entity : entities) { 098 tableInfo.initVersionValueIfNecessary(entity); 099 tableInfo.initTenantIdIfNecessary(entity); 100 tableInfo.initLogicDeleteValueIfNecessary(entity); 101 102 //执行 onInsert 监听器 103 tableInfo.invokeOnInsertListener(entity); 104 } 105 106 107 Object[] allValues = FlexConsts.EMPTY_ARRAY; 108 for (Object entity : entities) { 109 allValues = ArrayUtil.concat(allValues, tableInfo.buildInsertSqlArgs(entity, false)); 110 } 111 112 ProviderUtil.setSqlArgs(params, allValues); 113 114 return DialectFactory.getDialect().forInsertEntityBatch(tableInfo, entities); 115 } 116 117 118 /** 119 * deleteById 的 sql 构建 120 * 121 * @param params 122 * @param context 123 * @return sql 124 * @see com.mybatisflex.core.BaseMapper#deleteById(Serializable) 125 */ 126 public static String deleteById(Map params, ProviderContext context) { 127 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 128 if (ArrayUtil.isEmpty(primaryValues)) { 129 throw FlexExceptions.wrap("primaryValues can not be null or empty."); 130 } 131 132 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 133 134 Object[] allValues = ArrayUtil.concat(primaryValues, tableInfo.buildTenantIdArgs()); 135 ProviderUtil.setSqlArgs(params, allValues); 136 137 return DialectFactory.getDialect().forDeleteEntityById(tableInfo); 138 } 139 140 141 /** 142 * deleteBatchByIds 的 sql 构建 143 * 144 * @param params 145 * @param context 146 * @return sql 147 * @see com.mybatisflex.core.BaseMapper#deleteBatchByIds(Collection) 148 */ 149 public static String deleteBatchByIds(Map params, ProviderContext context) { 150 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 151 if (ArrayUtil.isEmpty(primaryValues)) { 152 throw FlexExceptions.wrap("primaryValues can not be null or empty."); 153 } 154 155 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 156 157 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 158 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(primaryValues, tenantIdArgs)); 159 160 return DialectFactory.getDialect().forDeleteEntityBatchByIds(tableInfo, primaryValues); 161 } 162 163 164 /** 165 * deleteByQuery 的 sql 构建 166 * 167 * @param params 168 * @param context 169 * @return sql 170 * @see com.mybatisflex.core.BaseMapper#deleteByQuery(QueryWrapper) 171 */ 172 public static String deleteByQuery(Map params, ProviderContext context) { 173 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 174 if (queryWrapper == null) { 175 throw FlexExceptions.wrap("queryWrapper can not be null or empty."); 176 } 177 178 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 179 CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName()); 180 181 tableInfo.appendConditions(null, queryWrapper); 182 ProviderUtil.setSqlArgs(params, CPI.getValueArray(queryWrapper)); 183 184 185 return DialectFactory.getDialect().forDeleteEntityBatchByQuery(tableInfo, queryWrapper); 186 } 187 188 189 /** 190 * update 的 sql 构建 191 * 192 * @param params 193 * @param context 194 * @return sql 195 * @see com.mybatisflex.core.BaseMapper#update(Object, boolean) 196 */ 197 public static String update(Map params, ProviderContext context) { 198 Object entity = ProviderUtil.getEntity(params); 199 if (entity == null) { 200 throw FlexExceptions.wrap("entity can not be null"); 201 } 202 203 boolean ignoreNulls = ProviderUtil.isIgnoreNulls(params); 204 205 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 206 207 //执行 onUpdate 监听器 208 tableInfo.invokeOnUpdateListener(entity); 209 210 Object[] updateValues = tableInfo.buildUpdateSqlArgs(entity, ignoreNulls, false); 211 Object[] primaryValues = tableInfo.buildPkSqlArgs(entity); 212 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 213 214 FlexExceptions.assertAreNotNull(primaryValues, "The value of primary key must not be null, entity[%s]", entity); 215 216 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(updateValues, primaryValues, tenantIdArgs)); 217 218 return DialectFactory.getDialect().forUpdateEntity(tableInfo, entity, ignoreNulls); 219 } 220 221 222 /** 223 * updateByQuery 的 sql 构建 224 * 225 * @param params 226 * @param context 227 * @return sql 228 * @see com.mybatisflex.core.BaseMapper#updateByQuery(Object, boolean, QueryWrapper) 229 */ 230 public static String updateByQuery(Map params, ProviderContext context) { 231 Object entity = ProviderUtil.getEntity(params); 232 if (entity == null) { 233 throw FlexExceptions.wrap("entity can not be null"); 234 } 235 boolean ignoreNulls = ProviderUtil.isIgnoreNulls(params); 236 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 237 238 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 239 240 //处理逻辑删除 和 多租户等 241 tableInfo.appendConditions(entity, queryWrapper); 242 243 Object[] values = tableInfo.buildUpdateSqlArgs(entity, ignoreNulls, true); 244 Object[] queryParams = CPI.getValueArray(queryWrapper); 245 246 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(values, queryParams)); 247 248 return DialectFactory.getDialect().forUpdateEntityByQuery(tableInfo, entity, ignoreNulls, queryWrapper); 249 } 250 251 /** 252 * updateNumberByQuery 的 sql 构建 253 * 254 * @param params 255 * @param context 256 * @return sql 257 * @see com.mybatisflex.core.BaseMapper#updateNumberAddByQuery(String, Number, QueryWrapper) 258 */ 259 public static String updateNumberAddByQuery(Map params, ProviderContext context) { 260 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 261 262 String fieldName = ProviderUtil.getFieldName(params); 263 Number value = (Number) ProviderUtil.getValue(params); 264 265 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 266 267 //处理逻辑删除 和 多租户等 268 tableInfo.appendConditions(null, queryWrapper); 269 270 Object[] queryParams = CPI.getValueArray(queryWrapper); 271 272 ProviderUtil.setSqlArgs(params, queryParams); 273 274 return DialectFactory.getDialect().forUpdateNumberAddByQuery(tableInfo.getSchema(), tableInfo.getTableName(), fieldName, value, queryWrapper); 275 } 276 277 278 /** 279 * selectOneById 的 sql 构建 280 * 281 * @param params 282 * @param context 283 * @return sql 284 * @see com.mybatisflex.core.BaseMapper#selectOneById(Serializable) 285 */ 286 public static String selectOneById(Map params, ProviderContext context) { 287 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 288 if (ArrayUtil.isEmpty(primaryValues)) { 289 throw FlexExceptions.wrap("primaryValues can not be null or empty."); 290 } 291 292 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 293 294 Object[] allValues = ArrayUtil.concat(primaryValues, tableInfo.buildTenantIdArgs()); 295 296 ProviderUtil.setSqlArgs(params, allValues); 297 298 return DialectFactory.getDialect().forSelectOneEntityById(tableInfo); 299 } 300 301 302 /** 303 * selectListByIds 的 sql 构建 304 * 305 * @param params 306 * @param context 307 * @return sql 308 * @see com.mybatisflex.core.BaseMapper#selectListByIds(Collection) 309 */ 310 public static String selectListByIds(Map params, ProviderContext context) { 311 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 312 if (ArrayUtil.isEmpty(primaryValues)) { 313 throw FlexExceptions.wrap("primaryValues can not be null or empty."); 314 } 315 316 TableInfo tableInfo = ProviderUtil.getTableInfo(context); 317 318 Object[] allValues = ArrayUtil.concat(primaryValues, tableInfo.buildTenantIdArgs()); 319 ProviderUtil.setSqlArgs(params, allValues); 320 321 return DialectFactory.getDialect().forSelectEntityListByIds(tableInfo, primaryValues); 322 } 323 324 325 /** 326 * selectListByQuery 的 sql 构建 327 * 328 * @param params 329 * @param context 330 * @return sql 331 * @see com.mybatisflex.core.BaseMapper#selectListByQuery(QueryWrapper) 332 */ 333 public static String selectListByQuery(Map params, ProviderContext context) { 334 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 335 if (queryWrapper == null) { 336 throw FlexExceptions.wrap("queryWrapper can not be null."); 337 } 338 List<TableInfo> tableInfos = getTableInfos(context, queryWrapper); 339 for (TableInfo tableInfo : tableInfos) { 340 tableInfo.appendConditions(null, queryWrapper); 341 342 CPI.setSelectColumnsIfNecessary(queryWrapper, tableInfo.getDefaultQueryColumn()); 343 CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName()); 344 } 345 346 Object[] values = CPI.getValueArray(queryWrapper); 347 ProviderUtil.setSqlArgs(params, values); 348 349 return DialectFactory.getDialect().forSelectByQuery(queryWrapper); 350 } 351 352 /** 353 * selectCountByQuery 的 sql 构建 354 * 355 * @param params 356 * @param context 357 * @return sql 358 * @see com.mybatisflex.core.BaseMapper#selectObjectByQuery(QueryWrapper) 359 */ 360 public static String selectObjectByQuery(Map params, ProviderContext context) { 361 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 362 if (queryWrapper == null) { 363 throw FlexExceptions.wrap("queryWrapper can not be null."); 364 } 365 366 List<TableInfo> tableInfos = getTableInfos(context, queryWrapper); 367 368 for (TableInfo tableInfo : tableInfos) { 369 tableInfo.appendConditions(null, queryWrapper); 370 CPI.setFromIfNecessary(queryWrapper, tableInfo.getSchema(), tableInfo.getTableName()); 371 } 372 373 Object[] values = CPI.getValueArray(queryWrapper); 374 ProviderUtil.setSqlArgs(params, values); 375 376 return DialectFactory.getDialect().forSelectByQuery(queryWrapper); 377 } 378 379 380 private static List<TableInfo> getTableInfos(ProviderContext context, QueryWrapper queryWrapper) { 381 List<TableInfo> tableInfos; 382 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 383 if (CollectionUtil.isNotEmpty(queryTables)) { 384 tableInfos = new ArrayList<>(); 385 for (QueryTable queryTable : queryTables) { 386 String tableName = queryTable.getName(); 387 if (StringUtil.isNotBlank(tableName)) { 388 TableInfo tableInfo = TableInfoFactory.ofTableName(tableName); 389 if (tableInfo != null) { 390 tableInfos.add(tableInfo); 391 } 392 } 393 } 394 } else { 395 tableInfos = Collections.singletonList(ProviderUtil.getTableInfo(context)); 396 } 397 return tableInfos; 398 } 399 400 401}