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.row.Row; 023import com.mybatisflex.core.row.RowCPI; 024import com.mybatisflex.core.row.RowMapper; 025import com.mybatisflex.core.util.ArrayUtil; 026import com.mybatisflex.core.util.CollectionUtil; 027 028import java.util.*; 029 030public class RowSqlProvider { 031 032 033 public static final String METHOD_RAW_SQL = "providerRawSql"; 034 035 /** 036 * 不让实例化,使用静态方法的模式,效率更高,非静态方法每次都会实例化当前类 037 * 参考源码: {{@link org.apache.ibatis.builder.annotation.ProviderSqlSource#getBoundSql(Object)} 038 */ 039 private RowSqlProvider() { 040 } 041 042 /** 043 * 执行原生 sql 的方法 044 * 045 * @param params 046 * @return sql 047 * @see RowMapper#insertBySql(String, Object...) 048 * @see RowMapper#deleteBySql(String, Object...) 049 * @see RowMapper#updateBySql(String, Object...) 050 */ 051 public static String providerRawSql(Map params) { 052 return ProviderUtil.getSqlString(params); 053 } 054 055 /** 056 * insert 的 sql 构建 057 * 058 * @param params 059 * @return sql 060 * @see RowMapper#insert(String, Row) 061 */ 062 public static String insert(Map params) { 063 String tableName = ProviderUtil.getTableName(params); 064 Row row = ProviderUtil.getRow(params); 065 ProviderUtil.setSqlArgs(params, RowCPI.obtainModifyValues(row)); 066 return DialectFactory.getDialect().forInsertRow(tableName, row); 067 } 068 069 /** 070 * insertBatch 的 sql 构建 071 * 072 * @param params 073 * @return sql 074 * @see RowMapper#insertBatchWithFirstRowColumns(String, List) 075 */ 076 public static String insertBatchWithFirstRowColumns(Map params) { 077 String tableName = ProviderUtil.getTableName(params); 078 List<Row> rows = ProviderUtil.getRows(params); 079 if (rows == null || rows.isEmpty()) { 080 throw FlexExceptions.wrap("rows can not be null or empty."); 081 } 082 083 //让所有 row 的列顺序和值的数量与第条数据保持一致 084 //这个必须 new 一个 LinkedHashSet,因为 keepModifyAttrs 会清除 row 所有的 modifyAttrs 085 Set<String> modifyAttrs = new LinkedHashSet<>(rows.get(0).obtainModifyAttrs()); 086 rows.forEach(row -> RowCPI.keepModifyAttrs(row, modifyAttrs)); 087 088 089 Object[] values = new Object[]{}; 090 for (Row row : rows) { 091 values = ArrayUtil.concat(values, RowCPI.obtainModifyValues(row)); 092 } 093 ProviderUtil.setSqlArgs(params, values); 094 095 //sql: INSERT INTO `tb_table`(`name`, `sex`) VALUES (?, ?),(?, ?),(?, ?) 096 return DialectFactory.getDialect().forInsertBatchWithFirstRowColumns(tableName, rows); 097 } 098 099 /** 100 * deleteById 的 sql 构建 101 * 102 * @param params 103 * @return sql 104 * @see RowMapper#deleteById(String, String, Object) 105 */ 106 public static String deleteById(Map params) { 107 String tableName = ProviderUtil.getTableName(params); 108 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 109 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 110 111 if (primaryValues.length == 0) { 112 throw FlexExceptions.wrap("primaryValue can not be null"); 113 } else { 114 ProviderUtil.setSqlArgs(params, primaryValues); 115 } 116 117 return DialectFactory.getDialect().forDeleteById(tableName, primaryKeys); 118 } 119 120 /** 121 * deleteBatchByIds 的 sql 构建 122 * 123 * @param params 124 * @return sql 125 * @see RowMapper#deleteBatchByIds(String, String, Collection) 126 */ 127 public static String deleteBatchByIds(Map params) { 128 String tableName = ProviderUtil.getTableName(params); 129 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 130 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 131 132 ProviderUtil.setSqlArgs(params, primaryValues); 133 return DialectFactory.getDialect().forDeleteBatchByIds(tableName, primaryKeys, primaryValues); 134 } 135 136 137 /** 138 * deleteByQuery 的 sql 构建 139 * 140 * @param params 141 * @return sql 142 * @see RowMapper#deleteByQuery(String, QueryWrapper) 143 */ 144 public static String deleteByQuery(Map params) { 145 String tableName = ProviderUtil.getTableName(params); 146 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 147 CPI.setFromIfNecessary(queryWrapper, tableName); 148 149 Object[] valueArray = CPI.getValueArray(queryWrapper); 150 ProviderUtil.setSqlArgs(params, valueArray); 151 152 return DialectFactory.getDialect().forDeleteByQuery(queryWrapper); 153 } 154 155 /** 156 * updateById 的 sql 构建 157 * 158 * @param params 159 * @return sql 160 * @see RowMapper#updateById(String, Row) 161 */ 162 public static String updateById(Map params) { 163 String tableName = ProviderUtil.getTableName(params); 164 Row row = ProviderUtil.getRow(params); 165 ProviderUtil.setSqlArgs(params, RowCPI.obtainAllModifyValues(row)); 166 return DialectFactory.getDialect().forUpdateById(tableName, row); 167 } 168 169 170 /** 171 * updateByQuery 的 sql 构建 172 * 173 * @param params 174 * @return sql 175 * @see RowMapper#updateByQuery(String, Row, QueryWrapper) 176 */ 177 public static String updateByQuery(Map params) { 178 String tableName = ProviderUtil.getTableName(params); 179 Row data = ProviderUtil.getRow(params); 180 181 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 182 CPI.setFromIfNecessary(queryWrapper, tableName); 183 184 Object[] modifyValues = RowCPI.obtainModifyValues(data); 185 Object[] valueArray = CPI.getValueArray(queryWrapper); 186 187 ProviderUtil.setSqlArgs(params, ArrayUtil.concat(modifyValues, valueArray)); 188 189 return DialectFactory.getDialect().forUpdateByQuery(queryWrapper, data); 190 } 191 192 193 /** 194 * updateBatchById 的 sql 构建 195 * mysql 等链接配置需要开启 allowMultiQueries=true 196 * 197 * @param params 198 * @return sql 199 * @see RowMapper#updateBatchById(String, List) 200 */ 201 public static String updateBatchById(Map params) { 202 String tableName = ProviderUtil.getTableName(params); 203 List<Row> rows = ProviderUtil.getRows(params); 204 if (CollectionUtil.isEmpty(rows)) { 205 throw FlexExceptions.wrap("rows can not be null or empty."); 206 } 207 208 Object[] values = new Object[0]; 209 for (Row row : rows) { 210 values = ArrayUtil.concat(values, RowCPI.obtainAllModifyValues(row)); 211 } 212 ProviderUtil.setSqlArgs(params, values); 213 return DialectFactory.getDialect().forUpdateBatchById(tableName, rows); 214 } 215 216 217 /** 218 * selectOneById 的 sql 构建 219 * 220 * @param params 221 * @return sql 222 * @see RowMapper#selectOneById(String, String, Object) 223 */ 224 public static String selectOneById(Map params) { 225 String tableName = ProviderUtil.getTableName(params); 226 String[] primaryKeys = ProviderUtil.getPrimaryKeys(params); 227 Object[] primaryValues = ProviderUtil.getPrimaryValues(params); 228 229 ProviderUtil.setSqlArgs(params, primaryValues); 230 231 return DialectFactory.getDialect().forSelectOneById(tableName, primaryKeys, primaryValues); 232 } 233 234 235 /** 236 * selectListByQuery 的 sql 构建 237 * 238 * @param params 239 * @return sql 240 * @see RowMapper#selectListByQuery(String, QueryWrapper) 241 */ 242 public static String selectListByQuery(Map params) { 243 String tableName = ProviderUtil.getTableName(params); 244 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 245 CPI.setFromIfNecessary(queryWrapper, tableName); 246 247 Object[] valueArray = CPI.getValueArray(queryWrapper); 248 ProviderUtil.setSqlArgs(params, valueArray); 249 250 251 return DialectFactory.getDialect().forSelectListByQuery(queryWrapper); 252 } 253 254 /** 255 * selectCountByQuery 的 sql 构建 256 * 257 * @param params 258 * @return sql 259 * @see RowMapper#selectCountByQuery(String, QueryWrapper) 260 */ 261 public static String selectCountByQuery(Map params) { 262 String tableName = ProviderUtil.getTableName(params); 263 264 QueryWrapper queryWrapper = ProviderUtil.getQueryWrapper(params); 265 CPI.setFromIfNecessary(queryWrapper, tableName); 266 267 Object[] valueArray = CPI.getValueArray(queryWrapper); 268 ProviderUtil.setSqlArgs(params, valueArray); 269 270 return DialectFactory.getDialect().forSelectCountByQuery(queryWrapper); 271 } 272 273 274}