001/* 002 * Copyright (c) 2022-2025, 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.row; 017 018import com.mybatisflex.core.FlexConsts; 019import com.mybatisflex.core.query.QueryColumn; 020import com.mybatisflex.core.query.QueryCondition; 021import com.mybatisflex.core.query.QueryWrapper; 022import com.mybatisflex.core.update.RawValue; 023import com.mybatisflex.core.update.UpdateWrapper; 024import com.mybatisflex.core.util.ArrayUtil; 025import com.mybatisflex.core.util.CollectionUtil; 026import com.mybatisflex.core.util.ConvertUtil; 027import com.mybatisflex.core.util.LambdaGetter; 028import com.mybatisflex.core.util.LambdaUtil; 029import com.mybatisflex.core.util.SqlUtil; 030import com.mybatisflex.core.util.StringUtil; 031 032import java.math.BigDecimal; 033import java.math.BigInteger; 034import java.sql.Time; 035import java.sql.Timestamp; 036import java.time.LocalDateTime; 037import java.util.ArrayList; 038import java.util.Arrays; 039import java.util.Date; 040import java.util.HashMap; 041import java.util.HashSet; 042import java.util.LinkedHashMap; 043import java.util.LinkedHashSet; 044import java.util.List; 045import java.util.Map; 046import java.util.Set; 047import java.util.function.BooleanSupplier; 048import java.util.function.Predicate; 049 050public class Row extends LinkedHashMap<String, Object> implements UpdateWrapper<Row> { 051 052 //主键,多个主键用英文逗号隔开 053 private Set<RowKey> primaryKeys; 054 055 public static Row of(String key, Object value) { 056 Row row = new Row(); 057 return row.set(key, value); 058 } 059 060 @Override 061 public Map<String, Object> getUpdates() { 062 return this; 063 } 064 065 public static Row ofKey(String primaryKey, Object value) { 066 Row row = new Row(); 067 String[] primaryKeyStrings = primaryKey.split(","); 068 row.primaryKeys = new HashSet<>(primaryKeyStrings.length); 069 070 for (String primaryKeyString : primaryKeyStrings) { 071 row.primaryKeys.add(RowKey.of(primaryKeyString.trim())); 072 } 073 074 if (primaryKeyStrings.length > 1 && !value.getClass().isArray()) { 075 throw new IllegalArgumentException("The type of \"" + value + "\" must be an array."); 076 } 077 078 if (primaryKeyStrings.length == 1) { 079 row.put(primaryKey.trim(), value); 080 } else { 081 Object[] values = (Object[]) value; 082 for (int i = 0; i < primaryKeyStrings.length; i++) { 083 row.put(primaryKeyStrings[i].trim(), values[i]); 084 } 085 } 086 return row; 087 } 088 089 public static Row ofKey(RowKey... rowKeys) { 090 Row row = new Row(); 091 row.getPrimaryKeys().addAll(Arrays.asList(rowKeys)); 092 return row; 093 } 094 095 096 public static Row ofKey(RowKey rowKey, Object value) { 097 Row row = new Row(); 098 row.getPrimaryKeys().add(rowKey); 099 row.put(rowKey.keyColumn, value); 100 return row; 101 } 102 103 104 public static Row ofKey(RowKey[] rowKeys, Object[] value) { 105 Row row = new Row(); 106 row.getPrimaryKeys().addAll(Arrays.asList(rowKeys)); 107 for (int i = 0; i < rowKeys.length; i++) { 108 row.put(rowKeys[i].keyColumn, value[i]); 109 } 110 return row; 111 } 112 113 @Override 114 public Row set(String property, Object value, boolean isEffective) { 115 if (!isEffective) { 116 return this; 117 } 118 119 if (StringUtil.noText(property)) { 120 throw new IllegalArgumentException("key column not be null or empty."); 121 } 122 123 SqlUtil.keepColumnSafely(property); 124 125 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 126 super.put(property, new RawValue(value)); 127 } else { 128 super.put(property, value); 129 } 130 131 return this; 132 } 133 134 @Override 135 public Row set(QueryColumn property, Object value, boolean isEffective) { 136 if (!isEffective) { 137 return this; 138 } 139 140 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 141 super.put(property.getName(), new RawValue(value)); 142 } else { 143 super.put(property.getName(), value); 144 } 145 146 return this; 147 } 148 149 @Override 150 public <T> Row set(LambdaGetter<T> property, Object value, boolean isEffective) { 151 if (!isEffective) { 152 return this; 153 } 154 155 if (value instanceof QueryWrapper || value instanceof QueryCondition || value instanceof QueryColumn) { 156 super.put(LambdaUtil.getFieldName(property), new RawValue(value)); 157 } else { 158 super.put(LambdaUtil.getFieldName(property), value); 159 } 160 161 return this; 162 } 163 164 @Override 165 public Row setRaw(String property, Object value, boolean isEffective) { 166 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 167 } 168 169 @Override 170 public Row setRaw(QueryColumn property, Object value, boolean isEffective) { 171 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 172 } 173 174 @Override 175 public <T> Row setRaw(LambdaGetter<T> property, Object value, boolean isEffective) { 176 return (Row) UpdateWrapper.super.setRaw(property, value, isEffective); 177 } 178 179 180 @Override 181 public Row set(String property, Object value) { 182 return set(property, value, true); 183 } 184 185 @Override 186 public Row set(String property, Object value, BooleanSupplier isEffective) { 187 return set(property, value, isEffective.getAsBoolean()); 188 } 189 190 @Override 191 public <V> Row set(String property, V value, Predicate<V> isEffective) { 192 return set(property, value, isEffective.test(value)); 193 } 194 195 @Override 196 public Row set(QueryColumn property, Object value) { 197 return set(property, value, true); 198 } 199 200 @Override 201 public Row set(QueryColumn property, Object value, BooleanSupplier isEffective) { 202 return set(property, value, isEffective.getAsBoolean()); 203 } 204 205 @Override 206 public <V> Row set(QueryColumn property, V value, Predicate<V> isEffective) { 207 return set(property, value, isEffective.test(value)); 208 } 209 210 @Override 211 public <T> Row set(LambdaGetter<T> property, Object value) { 212 return set(property, value, true); 213 } 214 215 @Override 216 public <T> Row set(LambdaGetter<T> property, Object value, BooleanSupplier isEffective) { 217 return set(property, value, isEffective.getAsBoolean()); 218 } 219 220 @Override 221 public <T, V> Row set(LambdaGetter<T> property, V value, Predicate<V> isEffective) { 222 return set(property, value, isEffective.test(value)); 223 } 224 225 @Override 226 public Row setRaw(String property, Object value) { 227 return setRaw(property, value, true); 228 } 229 230 @Override 231 public Row setRaw(String property, Object value, BooleanSupplier isEffective) { 232 return setRaw(property, value, isEffective.getAsBoolean()); 233 } 234 235 @Override 236 public <V> Row setRaw(String property, V value, Predicate<V> isEffective) { 237 return setRaw(property, value, isEffective.test(value)); 238 } 239 240 @Override 241 public Row setRaw(QueryColumn property, Object value) { 242 return setRaw(property, value, true); 243 } 244 245 @Override 246 public Row setRaw(QueryColumn property, Object value, BooleanSupplier isEffective) { 247 return setRaw(property, value, isEffective.getAsBoolean()); 248 } 249 250 @Override 251 public <V> Row setRaw(QueryColumn property, V value, Predicate<V> isEffective) { 252 return setRaw(property, value, isEffective.test(value)); 253 } 254 255 @Override 256 public <T> Row setRaw(LambdaGetter<T> property, Object value) { 257 return setRaw(property, value, true); 258 } 259 260 @Override 261 public <T> Row setRaw(LambdaGetter<T> property, Object value, BooleanSupplier isEffective) { 262 return setRaw(property, value, isEffective.getAsBoolean()); 263 } 264 265 @Override 266 public <T, V> Row setRaw(LambdaGetter<T> property, V value, Predicate<V> isEffective) { 267 return setRaw(property, value, isEffective.test(value)); 268 } 269 270 public Object get(String key, Object defaultValue) { 271 Object result = super.get(key); 272 return result != null ? result : defaultValue; 273 } 274 275 public Object getIgnoreCase(String key) { 276 Object result = super.get(key); 277 if (result != null) { 278 return result; 279 } 280 281 String newKey = StringUtil.deleteChar(key, '_', '-'); 282 for (String innerKey : keySet()) { 283 if (newKey.equalsIgnoreCase(StringUtil.deleteChar(innerKey, '_', '-'))) { 284 return super.get(innerKey); 285 } 286 } 287 return null; 288 } 289 290 291 public Object getIgnoreCase(String key, Object defaultValue) { 292 Object result = getIgnoreCase(key); 293 return result != null ? result : defaultValue; 294 } 295 296 297 @Override 298 public Object put(String key, Object value) { 299 if (!containsKey(key)) { 300 return super.put(key, value); 301 } else { 302 for (int i = 1; i < 100; i++) { 303 String newKey = key + RowUtil.INDEX_SEPARATOR + 1; 304 if (!containsKey(newKey)) { 305 return super.put(newKey, value); 306 } 307 } 308 } 309 return super.put(key, value); 310 } 311 312 313 public String getString(String key) { 314 Object s = super.get(key); 315 return s != null ? s.toString() : null; 316 } 317 318 319 public String getString(String key, String defaultValue) { 320 Object s = super.get(key); 321 if (s == null) { 322 return defaultValue; 323 } 324 String r = s.toString(); 325 return r.trim().isEmpty() ? defaultValue : r; 326 } 327 328 public Integer getInt(String key) { 329 return ConvertUtil.toInt(super.get(key)); 330 } 331 332 public Integer getInt(String key, Integer defaultValue) { 333 Integer r = ConvertUtil.toInt(super.get(key)); 334 return r != null ? r : defaultValue; 335 } 336 337 public Long getLong(String key) { 338 return ConvertUtil.toLong(super.get(key)); 339 } 340 341 public Long getLong(String key, Long defaultValue) { 342 Long r = ConvertUtil.toLong(super.get(key)); 343 return r != null ? r : defaultValue; 344 } 345 346 public Double getDouble(String key) { 347 return ConvertUtil.toDouble(super.get(key)); 348 } 349 350 public Double getDouble(String key, Double defaultValue) { 351 Double r = ConvertUtil.toDouble(super.get(key)); 352 return r != null ? r : defaultValue; 353 } 354 355 public Float getFloat(String key, Float defaultValue) { 356 Float r = ConvertUtil.toFloat(super.get(key)); 357 return r != null ? r : defaultValue; 358 } 359 360 public Float getFloat(String key) { 361 return ConvertUtil.toFloat(super.get(key)); 362 } 363 364 365 public Short getShort(String key, Short defaultValue) { 366 Short r = ConvertUtil.toShort(super.get(key)); 367 return r != null ? r : defaultValue; 368 } 369 370 public Short getShort(String key) { 371 return ConvertUtil.toShort(super.get(key)); 372 } 373 374 public BigInteger getBigInteger(String key) { 375 return ConvertUtil.toBigInteger(super.get(key)); 376 } 377 378 public BigInteger getBigInteger(String key, BigInteger defaultValue) { 379 BigInteger r = ConvertUtil.toBigInteger(super.get(key)); 380 return r != null ? r : defaultValue; 381 } 382 383 public BigDecimal getBigDecimal(String key) { 384 return ConvertUtil.toBigDecimal(super.get(key)); 385 } 386 387 public BigDecimal getBigDecimal(String key, BigDecimal defaultValue) { 388 BigDecimal r = ConvertUtil.toBigDecimal(super.get(key)); 389 return r != null ? r : defaultValue; 390 } 391 392 public Boolean getBoolean(String key) { 393 return ConvertUtil.toBoolean(super.get(key)); 394 } 395 396 public Boolean getBoolean(String key, Boolean defaultValue) { 397 Boolean r = ConvertUtil.toBoolean(super.get(key)); 398 return r != null ? r : defaultValue; 399 } 400 401 public Date getDate(String key) { 402 return ConvertUtil.toDate(super.get(key)); 403 } 404 405 public Date getDate(String key, Date defaultValue) { 406 Date r = ConvertUtil.toDate(super.get(key)); 407 return r != null ? r : defaultValue; 408 } 409 410 public LocalDateTime getLocalDateTime(String key) { 411 return ConvertUtil.toLocalDateTime(super.get(key)); 412 } 413 414 public LocalDateTime getLocalDateTime(String key, LocalDateTime defaultValue) { 415 LocalDateTime r = ConvertUtil.toLocalDateTime(super.get(key)); 416 return r != null ? r : defaultValue; 417 } 418 419 public Time getTime(String key) { 420 return (Time) super.get(key); 421 } 422 423 public Time getTime(String key, Time defaultValue) { 424 Time r = (Time) super.get(key); 425 return r != null ? r : defaultValue; 426 } 427 428 public Timestamp getTimestamp(String key) { 429 return (Timestamp) super.get(key); 430 } 431 432 public Timestamp getTimestamp(String key, Timestamp defaultValue) { 433 Timestamp r = (Timestamp) super.get(key); 434 return r != null ? r : defaultValue; 435 } 436 437 public Byte getByte(String key) { 438 return ConvertUtil.toByte(super.get(key)); 439 } 440 441 public byte[] getBytes(String key) { 442 return (byte[]) super.get(key); 443 } 444 445 @Override 446 public Object remove(Object key) { 447 for (String innerKey : keySet()) { 448 if (innerKey.equalsIgnoreCase((String) key)) { 449 return super.remove(innerKey); 450 } 451 } 452 return null; 453 } 454 455 public <T> T toEntity(Class<T> entityClass) { 456 return RowUtil.toEntity(this, entityClass); 457 } 458 459 public <T> T toObject(Class<T> objectClass) { 460 return RowUtil.toObject(this, objectClass); 461 } 462 463 public Map<String, Object> toCamelKeysMap() { 464 Map<String, Object> ret = new HashMap<>(); 465 for (String key : keySet()) { 466 ret.put(StringUtil.underlineToCamel(key), get(key)); 467 } 468 return ret; 469 } 470 471 public Map<String, Object> toUnderlineKeysMap() { 472 Map<String, Object> ret = new HashMap<>(); 473 for (String key : keySet()) { 474 ret.put(StringUtil.camelToUnderline(key), get(key)); 475 } 476 return ret; 477 } 478 479 public Set<RowKey> getPrimaryKeys() { 480 if (primaryKeys == null) { 481 primaryKeys = new HashSet<>(); 482 } 483 return primaryKeys; 484 } 485 486 public void setPrimaryKeys(Set<RowKey> primaryKeys) { 487 this.primaryKeys = primaryKeys; 488 } 489 490 public void keep(String... columns) { 491 entrySet().removeIf(entry -> !ArrayUtil.contains(columns, entry.getKey())); 492 } 493 494 495 public void keep(Set<String> columns) { 496 entrySet().removeIf(entry -> !columns.contains(entry.getKey())); 497 } 498 499 500 Set<String> getModifyAttrs() { 501 int pkCount = primaryKeys != null ? primaryKeys.size() : 0; 502 if (pkCount == 0) { 503 return keySet(); 504 } 505 506 Set<String> attrs = new LinkedHashSet<>(keySet()); 507 attrs.removeIf(this::isPk); 508 return attrs; 509 } 510 511 Map<String, RawValue> getRawValueMap() { 512 Map<String, RawValue> map = new HashMap<>(); 513 forEach((s, o) -> { 514 if (o instanceof RawValue) { 515 map.put(s, (RawValue) o); 516 } 517 }); 518 return map; 519 } 520 521 522 /** 523 * 获取修改的值,值需要保持顺序,返回的内容不包含主键的值 524 */ 525 Object[] obtainModifyValuesWithoutPk() { 526 List<Object> values = new ArrayList<>(); 527 for (String key : keySet()) { 528 Object value = get(key); 529 if (isPk(key)) { 530 continue; 531 } 532 if (value instanceof RawValue) { 533 values.addAll(Arrays.asList(((RawValue) value).getParams())); 534 } else { 535 values.add(value); 536 } 537 } 538 return values.toArray(); 539 } 540 541 542 String[] obtainsPrimaryKeyStrings() { 543 String[] returnKeys = new String[primaryKeys.size()]; 544 int index = 0; 545 for (RowKey primaryKey : primaryKeys) { 546 returnKeys[index++] = primaryKey.keyColumn; 547 } 548 return returnKeys; 549 } 550 551 552 RowKey[] obtainsPrimaryKeys() { 553 return getPrimaryKeys().toArray(new RowKey[0]); 554 } 555 556 557 Object[] obtainsPrimaryValues() { 558 if (CollectionUtil.isEmpty(primaryKeys)) { 559 return FlexConsts.EMPTY_ARRAY; 560 } 561 Object[] values = new Object[primaryKeys.size()]; 562 563 int index = 0; 564 for (RowKey primaryKey : primaryKeys) { 565 values[index++] = get(primaryKey.keyColumn); 566 } 567 return values; 568 } 569 570 571 /** 572 * 获取更新的数据,主键后置 573 * 574 * @return 数据内容 575 */ 576 Object[] obtainUpdateValues() { 577 return ArrayUtil.concat(obtainModifyValuesWithoutPk(), obtainsPrimaryValues()); 578 } 579 580 581 public Object[] obtainInsertValues() { 582 List<Object> values = new ArrayList<>(); 583 584 if (primaryKeys != null && !primaryKeys.isEmpty()) { 585 for (RowKey primaryKey : primaryKeys) { 586 if (primaryKey.before) { 587 values.add(get(primaryKey.keyColumn)); 588 } 589 } 590 } 591 592 for (String key : keySet()) { 593 Object value = get(key); 594 if (isPk(key)) { 595 continue; 596 } 597 if (value instanceof RawValue) { 598 values.addAll(Arrays.asList(((RawValue) value).getParams())); 599 } else { 600 values.add(value); 601 } 602 } 603 604 return values.toArray(); 605 } 606 607 public Object[] obtainInsertValues(Set<String> withAttrs) { 608 List<Object> values = new ArrayList<>(); 609 for (String key : withAttrs) { 610 Object value = get(key); 611 values.add(value); 612 } 613 return values.toArray(); 614 } 615 616 617 public Set<String> getInsertAttrs() { 618 Set<String> attrs = new LinkedHashSet<>(); 619 if (primaryKeys != null && !primaryKeys.isEmpty()) { 620 for (RowKey primaryKey : primaryKeys) { 621 if (primaryKey.before) { 622 attrs.add(primaryKey.keyColumn); 623 } 624 } 625 } 626 attrs.addAll(keySet()); 627 return attrs; 628 } 629 630 private boolean isPk(String attr) { 631 if (primaryKeys != null && !primaryKeys.isEmpty()) { 632 for (RowKey primaryKey : primaryKeys) { 633 if (primaryKey.keyColumn.equalsIgnoreCase(attr)) { 634 return true; 635 } 636 } 637 } 638 return false; 639 } 640 641 642}