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