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.QueryWrapper; 023import com.mybatisflex.core.row.Row; 024import com.mybatisflex.core.row.RowCPI; 025import com.mybatisflex.core.row.RowMapper; 026import com.mybatisflex.core.table.TableInfo; 027import com.mybatisflex.core.table.TableInfoFactory; 028import com.mybatisflex.core.util.ArrayUtil; 029import com.mybatisflex.core.util.CollectionUtil; 030 031import java.util.*; 032 033public class RowSqlProvider { 034 035 036 public static final String METHOD_RAW_SQL = "providerRawSql"; 037 038 /** 039 * 不让实例化,使用静态方法的模式,效率更高,非静态方法每次都会实例化当前类 040 * 参考源码: {{@link org.apache.ibatis.builder.annotation.ProviderSqlSource#getBoundSql(Object)} 041 */ 042 private RowSqlProvider() { 043 } 044 045 /** 046 * 执行原生 sql 的方法 047 * 048 * @param params 049 * @return sql 050 * @see RowMapper#insertBySql(String, Object...) 051 * @see RowMapper#deleteBySql(String, Object...) 052 * @see RowMapper#updateBySql(String, Object...) 053 */ 054 public static String providerRawSql(Map params) { 055 return ProviderUtil.getSqlString(params); 056 } 057 058 /** 059 * insert 的 sql 构建 060 * 061 * @param params 062 * @return sql 063 * @see RowMapper#insert(String,String, Row) 064 */ 065 public static String insert(Map params) { 066 String tableName = ProviderUtil.getTableName(params); 067 String schema = ProviderUtil.getSchemaName(params); 068 Row row = ProviderUtil.getRow(params); 069 ProviderUtil.setSqlArgs(params, RowCPI.obtainModifyValues(row)); 070 return DialectFactory.getDialect().forInsertRow(schema,tableName, row); 071 } 072 073 /** 074 * insertBatch 的 sql 构建 075 * 076 * @param params 077 * @return sql 078 * @see RowMapper#insertBatchWithFirstRowColumns(String, String, List) 079 */ 080 public static String insertBatchWithFirstRowColumns(Map params) { 081 String tableName = ProviderUtil.getTableName(params); 082 String schema = ProviderUtil.getSchemaName(params); 083 List<Row> rows = ProviderUtil.getRows(params); 084 if (rows == null || rows.isEmpty()) { 085 throw FlexExceptions.wrap("rows can not be null or empty."); 086 } 087 088 // 让所有 row 的列顺序和值的数量与第条数据保持一致 089 // 这个必须 new 一个 LinkedHashSet,因为 keepModifyAttrs 会清除 row 所有的 modifyAttrs 090 Set<String> modifyAttrs = new LinkedHashSet<>(rows.get(0).obtainModifyAttrs()); 091 rows.forEach(row -> row.prepareAttrs(modifyAttrs)); 092 093 094 Object[] values = new Object[]{}; 095 for (Row row : rows) { 096 values = ArrayUtil.concat(values, RowCPI.obtainModifyValues(row)); 097 } 098 ProviderUtil.setSqlArgs(params, values); 099 100 //sql: INSERT INTO `tb_table`(`name`, `sex`) VALUES (?, ?),(?, ?),(?, ?) 101 return DialectFactory.getDialect().forInsertBatchWithFirstRowColumns(schema,tableName, rows); 102 } 103 104 /** 105 * deleteById 的 sql 构建 106 * 107 * @param params 108 * @return sql 109 * @see RowMapper#deleteById(String,String, String, Object) 110 */ 111 public static String deleteById(Map params) { 112 String schema = ProviderUtil.getSchemaName(params); 113 String tableName = ProviderUtil.getTableName(params); 114 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 115 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 116 117 if (primaryValues.length == 0) { 118 throw FlexExceptions.wrap("primaryValue can not be null"); 119 } else { 120 ProviderUtil.setSqlArgs(params, primaryValues); 121 } 122 123 return DialectFactory.getDialect().forDeleteById(schema, tableName, primaryKeys); 124 } 125 126 /** 127 * deleteBatchByIds 的 sql 构建 128 * 129 * @param params 130 * @return sql 131 * @see RowMapper#deleteBatchByIds(String, String, String, Collection) 132 */ 133 public static String deleteBatchByIds(Map params) { 134 String schema = ProviderUtil.getSchemaName(params); 135 String tableName = ProviderUtil.getTableName(params); 136 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 137 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 138 139 ProviderUtil.setSqlArgs(params, primaryValues); 140 return DialectFactory.getDialect().forDeleteBatchByIds(schema, tableName, primaryKeys, primaryValues); 141 } 142 143 144 /** 145 * deleteByQuery 的 sql 构建 146 * 147 * @param params 148 * @return sql 149 * @see RowMapper#deleteByQuery(String,String, QueryWrapper) 150 */ 151 public static String deleteByQuery(Map params) { 152 String schema = ProviderUtil.getSchemaName(params); 153 String tableName = ProviderUtil.getTableName(params); 154 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 155 CPI.setFromIfNecessary(queryWrapper, schema,tableName); 156 157 Object[] valueArray = CPI.getValueArray(queryWrapper); 158 ProviderUtil.setSqlArgs(params, valueArray); 159 160 return DialectFactory.getDialect().forDeleteByQuery(queryWrapper); 161 } 162 163 /** 164 * updateById 的 sql 构建 165 * 166 * @param params 167 * @return sql 168 * @see RowMapper#updateById(String, String, Row) 169 */ 170 public static String updateById(Map params) { 171 String schema = ProviderUtil.getSchemaName(params); 172 String tableName = ProviderUtil.getTableName(params); 173 Row row = ProviderUtil.getRow(params); 174 ProviderUtil.setSqlArgs(params, RowCPI.obtainAllModifyValues(row)); 175 return DialectFactory.getDialect().forUpdateById(schema, tableName, row); 176 } 177 178 179 /** 180 * updateByQuery 的 sql 构建 181 * 182 * @param params 183 * @return sql 184 * @see RowMapper#updateByQuery(String, String, Row, QueryWrapper) 185 */ 186 public static String updateByQuery(Map params) { 187 String schema = ProviderUtil.getSchemaName(params); 188 String tableName = ProviderUtil.getTableName(params); 189 Row data = ProviderUtil.getRow(params); 190 191 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 192 CPI.setFromIfNecessary(queryWrapper,schema, tableName); 193 194 Object[] modifyValues = RowCPI.obtainModifyValues(data); 195 Object[] valueArray = CPI.getValueArray(queryWrapper); 196 197 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(modifyValues, valueArray)); 198 199 return DialectFactory.getDialect().forUpdateByQuery(queryWrapper, data); 200 } 201 202 203 /** 204 * updateBatchById 的 sql 构建 205 * mysql 等链接配置需要开启 allowMultiQueries=true 206 * 207 * @param params 208 * @return sql 209 * @see RowMapper#updateBatchById(String, String, List) 210 */ 211 public static String updateBatchById(Map params) { 212 String schema = ProviderUtil.getSchemaName(params); 213 String tableName = ProviderUtil.getTableName(params); 214 List<Row> rows = ProviderUtil.getRows(params); 215 if (CollectionUtil.isEmpty(rows)) { 216 throw FlexExceptions.wrap("rows can not be null or empty."); 217 } 218 219 Object[] values = FlexConsts.EMPTY_ARRAY; 220 for (Row row : rows) { 221 values = ArrayUtil.concat(values, RowCPI.obtainAllModifyValues(row)); 222 } 223 ProviderUtil.setSqlArgs(params, values); 224 return DialectFactory.getDialect().forUpdateBatchById(schema,tableName, rows); 225 } 226 227 /** 228 * updateEntity 的 sql 构建 229 * 230 * @param params 231 * @return sql 232 * @see RowMapper#updateEntity(Object entities) 233 */ 234 public static String updateEntity(Map params) { 235 Object entity = ProviderUtil.getEntity(params); 236 if (entity == null) { 237 throw FlexExceptions.wrap("entity can not be null"); 238 } 239 240 // 该 Mapper 是通用 Mapper 无法通过 ProviderContext 获取,直接使用 TableInfoFactory 241 TableInfo tableInfo = TableInfoFactory.ofEntityClass(entity.getClass()); 242 243 // 执行 onUpdate 监听器 244 tableInfo.invokeOnUpdateListener(entity); 245 246 Object[] updateValues = tableInfo.buildUpdateSqlArgs(entity, false, false); 247 Object[] primaryValues = tableInfo.buildPkSqlArgs(entity); 248 Object[] tenantIdArgs = tableInfo.buildTenantIdArgs(); 249 250 FlexExceptions.assertAreNotNull(primaryValues, "The value of primary key must not be null, entity[%s]", entity); 251 252 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(updateValues, primaryValues, tenantIdArgs)); 253 254 return DialectFactory.getDialect().forUpdateEntity(tableInfo, entity, false); 255 } 256 257 /** 258 * 执行类似 update table set field=field+1 where ... 的场景 259 * 260 * @param params 261 * @return sql 262 * @see RowMapper#updateNumberAddByQuery(String, String, String, Number, QueryWrapper) 263 */ 264 public static String updateNumberAddByQuery(Map params) { 265 266 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 267 String schema = ProviderUtil.getSchemaName(params); 268 String tableName = ProviderUtil.getTableName(params); 269 String fieldName = ProviderUtil.getFieldName(params); 270 Number value = (Number) ProviderUtil.getValue(params); 271 272 273 Object[] queryParams = CPI.getValueArray(queryWrapper); 274 275 ProviderUtil.setSqlArgs(params, queryParams); 276 277 return DialectFactory.getDialect().forUpdateNumberAddByQuery(schema, tableName, fieldName, value, queryWrapper); 278 } 279 280 281 /** 282 * selectOneById 的 sql 构建 283 * 284 * @param params 285 * @return sql 286 * @see RowMapper#selectOneById(String, String, String, Object) 287 */ 288 public static String selectOneById(Map params) { 289 String schema = ProviderUtil.getSchemaName(params); 290 String tableName = ProviderUtil.getTableName(params); 291 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 292 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 293 294 ProviderUtil.setSqlArgs(params, primaryValues); 295 296 return DialectFactory.getDialect().forSelectOneById(schema,tableName, primaryKeys, primaryValues); 297 } 298 299 300 /** 301 * selectListByQuery 的 sql 构建 302 * 303 * @param params 304 * @return sql 305 * @see RowMapper#selectListByQuery(String, String, QueryWrapper) 306 */ 307 public static String selectListByQuery(Map params) { 308 String schema = ProviderUtil.getSchemaName(params); 309 String tableName = ProviderUtil.getTableName(params); 310 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 311 CPI.setFromIfNecessary(queryWrapper,schema, tableName); 312 313 Object[] valueArray = CPI.getValueArray(queryWrapper); 314 ProviderUtil.setSqlArgs(params, valueArray); 315 316 317 return DialectFactory.getDialect().forSelectByQuery(queryWrapper); 318 } 319 320 /** 321 * selectCountByQuery 的 sql 构建 322 * 323 * @param params 324 * @return sql 325 * @see RowMapper#selectCountByQuery(String, String, QueryWrapper) 326 */ 327 public static String selectObjectByQuery(Map params) { 328 String schema = ProviderUtil.getSchemaName(params); 329 String tableName = ProviderUtil.getTableName(params); 330 331 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 332 CPI.setFromIfNecessary(queryWrapper,schema,tableName); 333 334 Object[] valueArray = CPI.getValueArray(queryWrapper); 335 ProviderUtil.setSqlArgs(params, valueArray); 336 337 return DialectFactory.getDialect().forSelectByQuery(queryWrapper); 338 } 339 340 341}