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