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.table; 017 018import com.mybatisflex.annotation.Column; 019import com.mybatisflex.annotation.InsertListener; 020import com.mybatisflex.annotation.KeyType; 021import com.mybatisflex.annotation.SetListener; 022import com.mybatisflex.annotation.UpdateListener; 023import com.mybatisflex.core.FlexConsts; 024import com.mybatisflex.core.FlexGlobalConfig; 025import com.mybatisflex.core.constant.SqlConsts; 026import com.mybatisflex.core.constant.SqlOperator; 027import com.mybatisflex.core.dialect.IDialect; 028import com.mybatisflex.core.exception.FlexExceptions; 029import com.mybatisflex.core.exception.locale.LocalizedFormats; 030import com.mybatisflex.core.logicdelete.LogicDeleteManager; 031import com.mybatisflex.core.mybatis.TypeHandlerObject; 032import com.mybatisflex.core.query.CPI; 033import com.mybatisflex.core.query.Join; 034import com.mybatisflex.core.query.QueryColumn; 035import com.mybatisflex.core.query.QueryCondition; 036import com.mybatisflex.core.query.QueryMethods; 037import com.mybatisflex.core.query.QueryTable; 038import com.mybatisflex.core.query.QueryWrapper; 039import com.mybatisflex.core.query.SelectQueryColumn; 040import com.mybatisflex.core.query.SelectQueryTable; 041import com.mybatisflex.core.query.SqlOperators; 042import com.mybatisflex.core.query.UnionWrapper; 043import com.mybatisflex.core.row.Row; 044import com.mybatisflex.core.tenant.TenantManager; 045import com.mybatisflex.core.update.RawValue; 046import com.mybatisflex.core.update.UpdateWrapper; 047import com.mybatisflex.core.util.ArrayUtil; 048import com.mybatisflex.core.util.ClassUtil; 049import com.mybatisflex.core.util.CollectionUtil; 050import com.mybatisflex.core.util.ConvertUtil; 051import com.mybatisflex.core.util.EnumWrapper; 052import com.mybatisflex.core.util.FieldWrapper; 053import com.mybatisflex.core.util.ObjectUtil; 054import com.mybatisflex.core.util.SqlUtil; 055import com.mybatisflex.core.util.StringUtil; 056import org.apache.ibatis.mapping.ResultFlag; 057import org.apache.ibatis.mapping.ResultMap; 058import org.apache.ibatis.mapping.ResultMapping; 059import org.apache.ibatis.reflection.MetaObject; 060import org.apache.ibatis.reflection.Reflector; 061import org.apache.ibatis.reflection.ReflectorFactory; 062import org.apache.ibatis.session.Configuration; 063import org.apache.ibatis.type.TypeHandler; 064import org.apache.ibatis.util.MapUtil; 065 066import java.lang.reflect.Field; 067import java.lang.reflect.Proxy; 068import java.sql.ResultSet; 069import java.sql.SQLException; 070import java.util.ArrayList; 071import java.util.Arrays; 072import java.util.Collections; 073import java.util.HashMap; 074import java.util.HashSet; 075import java.util.LinkedHashMap; 076import java.util.LinkedHashSet; 077import java.util.List; 078import java.util.Map; 079import java.util.Objects; 080import java.util.Set; 081import java.util.StringJoiner; 082import java.util.concurrent.ConcurrentHashMap; 083import java.util.function.Function; 084import java.util.stream.Collectors; 085import java.util.stream.Stream; 086 087import static com.mybatisflex.core.constant.SqlConsts.AND; 088import static com.mybatisflex.core.constant.SqlConsts.EQUALS_PLACEHOLDER; 089import static com.mybatisflex.core.constant.SqlConsts.IN; 090 091public class TableInfo { 092 093 private String schema; //schema 094 private String tableName; //表名 095 private Class<?> entityClass; //实体类 096 private boolean camelToUnderline = true; 097 private String dataSource; 098 099 //逻辑删除数据库列名 100 private String logicDeleteColumn; 101 102 //乐观锁字段 103 private String versionColumn; 104 105 //租户ID 字段 106 private String tenantIdColumn; 107 108 //数据插入时,默认插入数据字段 109 private Map<String, String> onInsertColumns; 110 111 //数据更新时,默认更新内容的字段 112 private Map<String, String> onUpdateColumns; 113 114 //大字段列 115 private String[] largeColumns = new String[0]; 116 117 private String[] allColumns = new String[0]; 118 119 //所有的字段,但除了主键的列 120 private String[] columns = new String[0]; 121 122 //主键字段 123 private String[] primaryColumns = new String[0]; 124 125 // 默认查询列,排除 large 等字段 126 private String[] defaultQueryColumns = new String[0]; 127 128 //在插入数据的时候,支持主动插入的主键字段,自增字段不需要主动插入 129 //但通过自定义生成器生成 或者 Sequence 在 before 生成的时候,是需要主动插入数据的 130 private String[] insertPrimaryKeys; 131 132 private List<ColumnInfo> columnInfoList; 133 private List<IdInfo> primaryKeyList; 134 135 //column 和 java 属性的称的关系映射 136 private final Map<String, ColumnInfo> columnInfoMapping = new HashMap<>(); 137 private final Map<String, QueryColumn> columnQueryMapping = new HashMap<>(); 138 139 //property:column 140 private final Map<String, String> propertyColumnMapping = new LinkedHashMap<>(); 141 142 private List<InsertListener> onInsertListeners; 143 private List<UpdateListener> onUpdateListeners; 144 private List<SetListener> onSetListeners; 145 146 /** 147 * 对应 MapperXML 配置文件中 {@code <resultMap>} 标签下的 {@code <association>} 标签。 148 */ 149 private Map<String, Class<?>> associationType; 150 151 /** 152 * 对应 MapperXML 配置文件中 {@code <resultMap>} 标签下的 {@code <collection>} 标签。 153 */ 154 private Map<Field, Class<?>> collectionType; 155 156 157 private final ReflectorFactory reflectorFactory = new BaseReflectorFactory() { 158 @Override 159 public Reflector findForClass(Class<?> type) { 160 return getReflector(); 161 } 162 }; 163 private Reflector reflector; //反射工具 164 165 public String getSchema() { 166 return schema; 167 } 168 169 public void setSchema(String schema) { 170 this.schema = schema; 171 } 172 173 public String getTableName() { 174 return tableName; 175 } 176 177 public String getTableNameWithSchema() { 178 return StringUtil.buildSchemaWithTable(schema, tableName); 179 } 180 181 public String getWrapSchemaAndTableName(IDialect dialect) { 182 if (StringUtil.isNotBlank(schema)) { 183 String table = dialect.getRealTable(tableName); 184 return dialect.wrap(dialect.getRealSchema(schema, table)) + "." + dialect.wrap(table); 185 } else { 186 return dialect.wrap(dialect.getRealTable(tableName)); 187 } 188 } 189 190 public void setTableName(String tableName) { 191 int indexOf = tableName.indexOf("."); 192 if (indexOf > 0) { 193 if (StringUtil.isBlank(schema)) { 194 this.schema = tableName.substring(0, indexOf); 195 this.tableName = tableName.substring(indexOf + 1); 196 } else { 197 this.tableName = tableName; 198 } 199 } else { 200 this.tableName = tableName; 201 } 202 } 203 204 public Class<?> getEntityClass() { 205 return entityClass; 206 } 207 208 public void setEntityClass(Class<?> entityClass) { 209 this.entityClass = entityClass; 210 } 211 212 public boolean isCamelToUnderline() { 213 return camelToUnderline; 214 } 215 216 public void setCamelToUnderline(boolean camelToUnderline) { 217 this.camelToUnderline = camelToUnderline; 218 } 219 220 public String getDataSource() { 221 return dataSource; 222 } 223 224 public void setDataSource(String dataSource) { 225 this.dataSource = dataSource; 226 } 227 228 public String getLogicDeleteColumnOrSkip() { 229 return LogicDeleteManager.getLogicDeleteColumn(logicDeleteColumn); 230 } 231 232 public String getLogicDeleteColumn() { 233 return logicDeleteColumn; 234 } 235 236 public void setLogicDeleteColumn(String logicDeleteColumn) { 237 this.logicDeleteColumn = logicDeleteColumn; 238 } 239 240 public String getVersionColumn() { 241 return versionColumn; 242 } 243 244 public void setVersionColumn(String versionColumn) { 245 this.versionColumn = versionColumn; 246 } 247 248 public String getTenantIdColumn() { 249 return tenantIdColumn; 250 } 251 252 public void setTenantIdColumn(String tenantIdColumn) { 253 this.tenantIdColumn = tenantIdColumn; 254 } 255 256 public Map<String, String> getOnInsertColumns() { 257 return onInsertColumns; 258 } 259 260 public void setOnInsertColumns(Map<String, String> onInsertColumns) { 261 this.onInsertColumns = onInsertColumns; 262 } 263 264 public Map<String, String> getOnUpdateColumns() { 265 return onUpdateColumns; 266 } 267 268 public void setOnUpdateColumns(Map<String, String> onUpdateColumns) { 269 this.onUpdateColumns = onUpdateColumns; 270 } 271 272 public String[] getLargeColumns() { 273 return largeColumns; 274 } 275 276 public void setLargeColumns(String[] largeColumns) { 277 this.largeColumns = largeColumns; 278 } 279 280 public String[] getDefaultQueryColumns() { 281 return defaultQueryColumns; 282 } 283 284 public void setDefaultQueryColumns(String[] defaultQueryColumns) { 285 this.defaultQueryColumns = defaultQueryColumns; 286 } 287 288 public String[] getInsertPrimaryKeys() { 289 return insertPrimaryKeys; 290 } 291 292 public void setInsertPrimaryKeys(String[] insertPrimaryKeys) { 293 this.insertPrimaryKeys = insertPrimaryKeys; 294 } 295 296 public Reflector getReflector() { 297 return reflector; 298 } 299 300 public ReflectorFactory getReflectorFactory() { 301 return reflectorFactory; 302 } 303 304 public void setReflector(Reflector reflector) { 305 this.reflector = reflector; 306 } 307 308 public String[] getAllColumns() { 309 return allColumns; 310 } 311 312 public void setAllColumns(String[] allColumns) { 313 this.allColumns = allColumns; 314 } 315 316 public String[] getColumns() { 317 return columns; 318 } 319 320 321 public void setColumns(String[] columns) { 322 this.columns = columns; 323 } 324 325 public String[] getPrimaryColumns() { 326 return primaryColumns; 327 } 328 329 public void setPrimaryColumns(String[] primaryColumns) { 330 this.primaryColumns = primaryColumns; 331 } 332 333 334 public List<InsertListener> getOnInsertListeners() { 335 return onInsertListeners; 336 } 337 338 public void setOnInsertListeners(List<InsertListener> onInsertListeners) { 339 this.onInsertListeners = onInsertListeners; 340 } 341 342 public List<UpdateListener> getOnUpdateListeners() { 343 return onUpdateListeners; 344 } 345 346 public void setOnUpdateListeners(List<UpdateListener> onUpdateListeners) { 347 this.onUpdateListeners = onUpdateListeners; 348 } 349 350 public List<SetListener> getOnSetListeners() { 351 return onSetListeners; 352 } 353 354 public void setOnSetListeners(List<SetListener> onSetListeners) { 355 this.onSetListeners = onSetListeners; 356 } 357 358 public List<ColumnInfo> getColumnInfoList() { 359 return columnInfoList; 360 } 361 362 public String getColumnByProperty(String property) { 363 String column = propertyColumnMapping.get(property); 364 return StringUtil.isNotBlank(column) ? column : property; 365 } 366 367 public Map<String, Class<?>> getAssociationType() { 368 return associationType; 369 } 370 371 public void setAssociationType(Map<String, Class<?>> associationType) { 372 this.associationType = associationType; 373 } 374 375 public void addAssociationType(String fieldName, Class<?> clazz) { 376 if (associationType == null) { 377 associationType = new HashMap<>(); 378 } 379 associationType.put(fieldName, clazz); 380 } 381 382 public Map<Field, Class<?>> getCollectionType() { 383 return collectionType; 384 } 385 386 public void setCollectionType(Map<Field, Class<?>> collectionType) { 387 this.collectionType = collectionType; 388 } 389 390 public void addCollectionType(Field field, Class<?> genericClass) { 391 if (collectionType == null) { 392 collectionType = new HashMap<>(); 393 } 394 collectionType.put(field, genericClass); 395 } 396 397 void setColumnInfoList(List<ColumnInfo> columnInfoList) { 398 this.columnInfoList = columnInfoList; 399 List<String> columnNames = new ArrayList<>(); 400 for (int i = 0; i < columnInfoList.size(); i++) { 401 ColumnInfo columnInfo = columnInfoList.get(i); 402 //真正的字段(没有做忽略标识) 403 if (!columnInfo.isIgnore()) { 404 columnNames.add(columnInfo.column); 405 406 columnInfoMapping.put(columnInfo.column, columnInfo); 407 propertyColumnMapping.put(columnInfo.property, columnInfo.column); 408 409 String[] alias = columnInfo.getAlias(); 410 columnQueryMapping.put(columnInfo.column, new QueryColumn(schema, tableName, columnInfo.column, alias != null && alias.length > 0 ? alias[0] : null)); 411 } 412 } 413 414 this.columns = columnNames.toArray(new String[]{}); 415 this.allColumns = ArrayUtil.concat(allColumns, columns); 416 } 417 418 419 public List<IdInfo> getPrimaryKeyList() { 420 return primaryKeyList; 421 } 422 423 void setPrimaryKeyList(List<IdInfo> primaryKeyList) { 424 this.primaryKeyList = primaryKeyList; 425 this.primaryColumns = new String[primaryKeyList.size()]; 426 427 List<String> insertIdFields = new ArrayList<>(); 428 429 for (int i = 0; i < primaryKeyList.size(); i++) { 430 IdInfo idInfo = primaryKeyList.get(i); 431 primaryColumns[i] = idInfo.getColumn(); 432 433 if (idInfo.getKeyType() != KeyType.Auto 434 && (idInfo.getBefore() != null && idInfo.getBefore()) 435 ) { 436 insertIdFields.add(idInfo.getColumn()); 437 } 438 439 columnInfoMapping.put(idInfo.column, idInfo); 440 propertyColumnMapping.put(idInfo.property, idInfo.column); 441 442 String[] alias = idInfo.getAlias(); 443 columnQueryMapping.put(idInfo.column, new QueryColumn(schema, tableName, idInfo.column, alias != null && alias.length > 0 ? alias[0] : null)); 444 } 445 this.allColumns = ArrayUtil.concat(allColumns, primaryColumns); 446 this.insertPrimaryKeys = insertIdFields.toArray(new String[0]); 447 } 448 449 450 /** 451 * 构建 insert 的 Sql 参数 452 * 453 * @param entity 从 entity 中获取 454 * @param ignoreNulls 是否忽略 null 值 455 * @return 数组 456 */ 457 public Object[] buildInsertSqlArgs(Object entity, boolean ignoreNulls) { 458 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 459 String[] insertColumns = obtainInsertColumns(entity, ignoreNulls); 460 461 Map<String, RawValue> rawValueMap = obtainUpdateRawValueMap(entity); 462 463 List<Object> values = new ArrayList<>(insertColumns.length); 464 for (String insertColumn : insertColumns) { 465 if (onInsertColumns == null || !onInsertColumns.containsKey(insertColumn)) { 466 if (rawValueMap.containsKey(insertColumn)) { 467 continue; 468 } 469 Object value = buildColumnSqlArg(metaObject, insertColumn); 470 if (ignoreNulls && value == null) { 471 continue; 472 } 473 values.add(value); 474 } 475 } 476 return values.toArray(); 477 } 478 479 /** 480 * 插入(新增)数据时,获取所有要插入的字段 481 * 482 * @param entity 483 * @param ignoreNulls 484 * @return 字段列表 485 */ 486 public String[] obtainInsertColumns(Object entity, boolean ignoreNulls) { 487 if (!ignoreNulls) { 488 return ArrayUtil.concat(insertPrimaryKeys, columns); 489 } 490 // 忽略 null 字段, 491 else { 492 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 493 List<String> retColumns = new ArrayList<>(); 494 for (String insertColumn : allColumns) { 495 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 496 retColumns.add(insertColumn); 497 } else { 498 Object value = buildColumnSqlArg(metaObject, insertColumn); 499 if (value == null) { 500 continue; 501 } 502 retColumns.add(insertColumn); 503 } 504 } 505 return retColumns.toArray(new String[0]); 506 } 507 } 508 509 510 public Object[] buildInsertSqlArgsWithPk(Object entity, boolean ignoreNulls) { 511 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 512 String[] insertColumns = obtainInsertColumnsWithPk(entity, ignoreNulls); 513 514 List<Object> values = new ArrayList<>(insertColumns.length); 515 for (String insertColumn : insertColumns) { 516 if (onInsertColumns == null || !onInsertColumns.containsKey(insertColumn)) { 517 Object value = buildColumnSqlArg(metaObject, insertColumn); 518 if (ignoreNulls && value == null) { 519 continue; 520 } 521 values.add(value); 522 } 523 } 524 return values.toArray(); 525 } 526 527 528 /** 529 * 插入(新增)数据时,获取所有要插入的字段 530 * 531 * @param entity 532 * @param ignoreNulls 533 * @return 字段列表 534 */ 535 public String[] obtainInsertColumnsWithPk(Object entity, boolean ignoreNulls) { 536 if (!ignoreNulls) { 537 return allColumns; 538 } else { 539 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 540 List<String> retColumns = new ArrayList<>(); 541 for (String primaryKey : primaryColumns) { 542 Object value = buildColumnSqlArg(metaObject, primaryKey); 543 if (value == null) { 544 throw new IllegalArgumentException("Entity Primary Key value must not be null."); 545 } 546 retColumns.add(primaryKey); 547 } 548 for (String insertColumn : columns) { 549 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 550 retColumns.add(insertColumn); 551 } else { 552 Object value = buildColumnSqlArg(metaObject, insertColumn); 553 if (value == null) { 554 continue; 555 } 556 retColumns.add(insertColumn); 557 } 558 } 559 return retColumns.toArray(new String[0]); 560 } 561 } 562 563 564 @SuppressWarnings({"unchecked", "rawtypes"}) 565 public Map<String, RawValue> obtainUpdateRawValueMap(Object entity) { 566 if (!(entity instanceof UpdateWrapper)) { 567 return Collections.emptyMap(); 568 } 569 570 Map<String, Object> updates = ((UpdateWrapper) entity).getUpdates(); 571 if (updates.isEmpty()) { 572 return Collections.emptyMap(); 573 } 574 575 Map<String, RawValue> map = new HashMap<>(); 576 updates.forEach((key, value) -> { 577 if (value instanceof RawValue) { 578 String column = getColumnByProperty(key); 579 map.put(column, (RawValue) value); 580 } 581 }); 582 583 return map; 584 } 585 586 /** 587 * 获取要修改的值 588 * 589 * @param entity 590 * @param ignoreNulls 591 */ 592 public Set<String> obtainUpdateColumns(Object entity, boolean ignoreNulls, boolean includePrimary) { 593 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 594 Set<String> columns = new LinkedHashSet<>(); //需使用 LinkedHashSet 保证 columns 的顺序 595 if (entity instanceof UpdateWrapper) { 596 Map<String, Object> updates = ((UpdateWrapper) entity).getUpdates(); 597 if (updates.isEmpty()) { 598 return Collections.emptySet(); 599 } 600 for (String property : updates.keySet()) { 601 602 String column = getColumnByProperty(property); 603 604 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 605 continue; 606 } 607 608 //过滤乐观锁字段 和 租户字段 609 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 610 continue; 611 } 612 613 if (!includePrimary && ArrayUtil.contains(primaryColumns, column)) { 614 continue; 615 } 616 617// Object value = updates.get(property); 618 // ModifyAttrsRecord 忽略 ignoreNulls 的设置 619 // Object value = getPropertyValue(metaObject, property); 620 // if (ignoreNulls && value == null) { 621 // continue; 622 // } 623 columns.add(column); 624 } 625 } 626 //not ModifyAttrsRecord 627 else { 628 for (String column : this.columns) { 629 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 630 continue; 631 } 632 633 //过滤乐观锁字段 和 租户字段 634 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 635 continue; 636 } 637 638 Object value = buildColumnSqlArg(metaObject, column); 639 if (ignoreNulls && value == null) { 640 continue; 641 } 642 643 columns.add(column); 644 } 645 } 646 return columns; 647 } 648 649 /** 650 * 获取所有要修改的值,默认为全部除了主键以外的字段 651 * 652 * @param entity 实体对象 653 * @return 数组 654 */ 655 public Object[] buildUpdateSqlArgs(Object entity, boolean ignoreNulls, boolean includePrimary) { 656 657 List<Object> values = new ArrayList<>(); 658 if (entity instanceof UpdateWrapper) { 659 Map<String, Object> updates = ((UpdateWrapper) entity).getUpdates(); 660 if (updates.isEmpty()) { 661 return FlexConsts.EMPTY_ARRAY; 662 } 663 for (String property : updates.keySet()) { 664 665 String column = getColumnByProperty(property); 666 667 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 668 continue; 669 } 670 //过滤乐观锁字段 和 租户字段 671 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 672 continue; 673 } 674 675 if (!includePrimary && ArrayUtil.contains(primaryColumns, column)) { 676 continue; 677 } 678 679 Object value = updates.get(property); 680 if (value instanceof RawValue) { 681 continue; 682 } 683 684 if (value != null) { 685 ColumnInfo columnInfo = columnInfoMapping.get(column); 686 if (columnInfo != null) { 687 TypeHandler typeHandler = columnInfo.buildTypeHandler(null); 688 if (typeHandler != null) { 689 value = new TypeHandlerObject(typeHandler, value, columnInfo.getJdbcType()); 690 } 691 } 692 693 // fixed: https://gitee.com/mybatis-flex/mybatis-flex/issues/I7TFBK 694 if (value.getClass().isEnum()) { 695 EnumWrapper enumWrapper = EnumWrapper.of(value.getClass()); 696 if (enumWrapper.hasEnumValueAnnotation()) { 697 value = enumWrapper.getEnumValue((Enum) value); 698 } else { 699 value = ((Enum<?>) value).name(); 700 } 701 } 702 } 703 704 // ModifyAttrsRecord 忽略 ignoreNulls 的设置, 705 // 当使用 ModifyAttrsRecord 时,可以理解为要对字段进行 null 值进行更新,否则没必要使用 ModifyAttrsRecord 706 // if (ignoreNulls && value == null) { 707 // continue; 708 // } 709 values.add(value); 710 } 711 } 712 // normal entity. not ModifyAttrsRecord 713 else { 714 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 715 716 for (String column : this.columns) { 717 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 718 continue; 719 } 720 721 //过滤乐观锁字段 和 租户字段 722 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 723 continue; 724 } 725 726 // 普通 entity 忽略 includePrimary 的设置, 727 // 因为 for 循环中的 this.columns 本身就不包含有主键 728 // if (includePrimary) { 729 // } 730 731 Object value = buildColumnSqlArg(metaObject, column); 732 if (ignoreNulls && value == null) { 733 continue; 734 } 735 736 values.add(value); 737 } 738 } 739 740 return values.toArray(); 741 } 742 743 744 /** 745 * 构建主键的 sql 参数数据 746 * 747 * @param entity 748 */ 749 public Object[] buildPkSqlArgs(Object entity) { 750 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 751 Object[] values = new Object[primaryColumns.length]; 752 for (int i = 0; i < primaryColumns.length; i++) { 753 values[i] = buildColumnSqlArg(metaObject, primaryColumns[i]); 754 } 755 return values; 756 } 757 758 public Object getValue(Object entity, String property) { 759 FieldWrapper fieldWrapper = FieldWrapper.of(entityClass, property); 760 return fieldWrapper.get(entity); 761 } 762 763 /** 764 * 获取主键值 765 * 766 * @param entity 767 * @return 主键值,有多个主键时返回数组 768 */ 769 public Object getPkValue(Object entity) { 770 //绝大多数情况为 1 个主键 771 if (primaryColumns.length == 1) { 772 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 773 ColumnInfo columnInfo = columnInfoMapping.get(primaryColumns[0]); 774 return getPropertyValue(metaObject, columnInfo.property); 775 } 776 //多个主键 777 else if (primaryColumns.length > 1) { 778 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 779 Object[] values = new Object[primaryColumns.length]; 780 for (int i = 0; i < primaryColumns.length; i++) { 781 ColumnInfo columnInfo = columnInfoMapping.get(primaryColumns[i]); 782 values[i] = getPropertyValue(metaObject, columnInfo.property); 783 } 784 return values; 785 } 786 //无主键 787 else { 788 return null; 789 } 790 } 791 792 793 public Object[] buildTenantIdArgs() { 794 if (StringUtil.isBlank(tenantIdColumn)) { 795 return null; 796 } 797 798 return TenantManager.getTenantIds(); 799 } 800 801 802 public String buildTenantCondition(String sql, Object[] tenantIdArgs, IDialect dialect) { 803 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 804 if (tenantIdArgs.length == 1) { 805 return sql + AND + dialect.wrap(tenantIdColumn) + EQUALS_PLACEHOLDER; 806 } else { 807 return sql + AND + dialect.wrap(tenantIdColumn) + IN + SqlUtil.buildSqlParamPlaceholder(tenantIdArgs.length); 808 } 809 } else { 810 return sql; 811 } 812 } 813 814 public void buildTenantCondition(StringBuilder sql, Object[] tenantIdArgs, IDialect dialect) { 815 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 816 if (tenantIdArgs.length == 1) { 817 sql.append(AND).append(dialect.wrap(tenantIdColumn)).append(EQUALS_PLACEHOLDER); 818 } else { 819 sql.append(AND).append(dialect.wrap(tenantIdColumn)).append(IN).append(SqlUtil.buildSqlParamPlaceholder(tenantIdArgs.length)); 820 } 821 } 822 } 823 824 825 public void buildTenantCondition(QueryWrapper queryWrapper) { 826 Object[] tenantIdArgs = buildTenantIdArgs(); 827 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 828 if (tenantIdArgs.length == 1) { 829 queryWrapper.where(QueryCondition.create(schema, tableName, tenantIdColumn, SqlConsts.EQUALS, tenantIdArgs[0])); 830 } else { 831 queryWrapper.where(QueryCondition.create(schema, tableName, tenantIdColumn, SqlConsts.IN, tenantIdArgs)); 832 } 833 } 834 } 835 836 837 private static final String APPEND_CONDITIONS_FLAG = "appendConditions"; 838 839 public void appendConditions(Object entity, QueryWrapper queryWrapper) { 840 841 Object appendConditions = CPI.getContext(queryWrapper, APPEND_CONDITIONS_FLAG); 842 if (Boolean.TRUE.equals(appendConditions)) { 843 return; 844 } else { 845 CPI.putContext(queryWrapper, APPEND_CONDITIONS_FLAG, Boolean.TRUE); 846 } 847 848 //select xxx.id,(select..) from xxx 849 List<QueryColumn> selectColumns = CPI.getSelectColumns(queryWrapper); 850 if (selectColumns != null && !selectColumns.isEmpty()) { 851 for (QueryColumn queryColumn : selectColumns) { 852 if (queryColumn instanceof SelectQueryColumn) { 853 QueryWrapper selectColumnQueryWrapper = CPI.getQueryWrapper((SelectQueryColumn) queryColumn); 854 doAppendConditions(entity, selectColumnQueryWrapper); 855 } 856 } 857 } 858 859 //select * from (select ... from ) 中的子查询处理 860 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 861 if (queryTables != null && !queryTables.isEmpty()) { 862 for (QueryTable queryTable : queryTables) { 863 if (queryTable instanceof SelectQueryTable) { 864 QueryWrapper selectQueryWrapper = ((SelectQueryTable) queryTable).getQueryWrapper(); 865 doAppendConditions(entity, selectQueryWrapper); 866 } 867 } 868 } 869 870 //添加乐观锁条件,只有在 update 的时候进行处理 871 if (StringUtil.isNotBlank(versionColumn) && entity != null) { 872 Object versionValue = buildColumnSqlArg(entity, versionColumn); 873 if (versionValue == null) { 874 throw FlexExceptions.wrap(LocalizedFormats.ENTITY_VERSION_NULL, entity); 875 } 876 queryWrapper.and(QueryCondition.create(schema, tableName, versionColumn, SqlConsts.EQUALS, versionValue)); 877 } 878 879 //逻辑删除 880 if (StringUtil.isNotBlank(getLogicDeleteColumnOrSkip())) { 881 String joinTableAlias = CPI.getContext(queryWrapper, "joinTableAlias"); 882 LogicDeleteManager.getProcessor().buildQueryCondition(queryWrapper, this, joinTableAlias); 883 } 884 885 //多租户 886 buildTenantCondition(queryWrapper); 887 888 889 //子查询 890 List<QueryWrapper> childSelects = CPI.getChildSelect(queryWrapper); 891 if (CollectionUtil.isNotEmpty(childSelects)) { 892 for (QueryWrapper childQueryWrapper : childSelects) { 893 doAppendConditions(entity, childQueryWrapper); 894 } 895 } 896 897 898 //join 899 List<Join> joins = CPI.getJoins(queryWrapper); 900 if (CollectionUtil.isNotEmpty(joins)) { 901 for (Join join : joins) { 902 QueryTable joinQueryTable = CPI.getJoinQueryTable(join); 903 904 //join select 905 if (joinQueryTable instanceof SelectQueryTable) { 906 QueryWrapper childQuery = ((SelectQueryTable) joinQueryTable).getQueryWrapper(); 907 doAppendConditions(entity, childQuery); 908 } 909 //join table 910 else { 911 String nameWithSchema = joinQueryTable.getNameWithSchema(); 912 if (StringUtil.isNotBlank(nameWithSchema)) { 913 TableInfo tableInfo = TableInfoFactory.ofTableName(nameWithSchema); 914 if (tableInfo != null) { 915 QueryCondition joinQueryCondition = CPI.getJoinQueryCondition(join); 916 QueryWrapper newWrapper = QueryWrapper.create() 917 .where(joinQueryCondition); 918 CPI.putContext(newWrapper, "joinTableAlias", joinQueryTable.getAlias()); 919 tableInfo.appendConditions(entity, newWrapper); 920 QueryCondition whereQueryCondition = CPI.getWhereQueryCondition(newWrapper); 921 CPI.setJoinQueryCondition(join, whereQueryCondition); 922 } 923 } 924 } 925 } 926 } 927 928 //union 929 List<UnionWrapper> unions = CPI.getUnions(queryWrapper); 930 if (CollectionUtil.isNotEmpty(unions)) { 931 for (UnionWrapper union : unions) { 932 QueryWrapper unionQueryWrapper = union.getQueryWrapper(); 933 doAppendConditions(entity, unionQueryWrapper); 934 } 935 } 936 } 937 938 939 private void doAppendConditions(Object entity, QueryWrapper queryWrapper) { 940 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 941 if (queryTables != null && !queryTables.isEmpty()) { 942 for (QueryTable queryTable : queryTables) { 943 if (queryTable instanceof SelectQueryTable) { 944 QueryWrapper childQuery = ((SelectQueryTable) queryTable).getQueryWrapper(); 945 doAppendConditions(entity, childQuery); 946 } else { 947 String nameWithSchema = queryTable.getNameWithSchema(); 948 if (StringUtil.isNotBlank(nameWithSchema)) { 949 TableInfo tableInfo = TableInfoFactory.ofTableName(nameWithSchema); 950 if (tableInfo != null) { 951 tableInfo.appendConditions(entity, queryWrapper); 952 } 953 } 954 } 955 } 956 } 957 } 958 959 960 public QueryWrapper buildQueryWrapper(Object entity, SqlOperators operators) { 961 QueryColumn[] queryColumns = new QueryColumn[defaultQueryColumns.length]; 962 for (int i = 0; i < defaultQueryColumns.length; i++) { 963 queryColumns[i] = columnQueryMapping.get(defaultQueryColumns[i]); 964 } 965 966 QueryWrapper queryWrapper = QueryWrapper.create(); 967 968 String tableNameWithSchema = getTableNameWithSchema(); 969 queryWrapper.select(queryColumns).from(tableNameWithSchema); 970 971 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 972 propertyColumnMapping.forEach((property, column) -> { 973 if (column.equals(logicDeleteColumn)) { 974 return; 975 } 976 Object value = metaObject.getValue(property); 977 if (value != null && !"".equals(value)) { 978 QueryColumn queryColumn = buildQueryColumn(column); 979 if (operators != null && operators.containsKey(property)) { 980 SqlOperator operator = operators.get(property); 981 if (operator == SqlOperator.LIKE || operator == SqlOperator.NOT_LIKE) { 982 value = "%" + value + "%"; 983 } 984 queryWrapper.and(QueryCondition.create(queryColumn, operator, value)); 985 } else { 986 queryWrapper.and(queryColumn.eq(value)); 987 } 988 } 989 }); 990 return queryWrapper; 991 } 992 993 994 public QueryColumn buildQueryColumn(String column) { 995 String tableNameWithSchema = getTableNameWithSchema(); 996 QueryColumn queryColumn = TableDefs.getQueryColumn(entityClass, tableNameWithSchema, column); 997 if (queryColumn == null) { 998 queryColumn = QueryMethods.column(tableNameWithSchema, column); 999 } 1000 return queryColumn; 1001 } 1002 1003 1004 public String getKeyProperties() { 1005 StringJoiner joiner = new StringJoiner(","); 1006 for (IdInfo value : primaryKeyList) { 1007 joiner.add(FlexConsts.ENTITY + "." + value.getProperty()); 1008 } 1009 return joiner.toString(); 1010 } 1011 1012 1013 public String getKeyColumns() { 1014 StringJoiner joiner = new StringJoiner(","); 1015 for (IdInfo value : primaryKeyList) { 1016 joiner.add(value.getColumn()); 1017 } 1018 return joiner.toString(); 1019 } 1020 1021 public List<QueryColumn> getDefaultQueryColumn() { 1022 return Arrays.stream(defaultQueryColumns) 1023 .map(columnQueryMapping::get) 1024 .collect(Collectors.toList()); 1025 } 1026 1027 1028 public ResultMap buildResultMap(Configuration configuration) { 1029 // 所有的嵌套类对象引用 1030 Stream<Class<?>> ct = collectionType == null ? Stream.empty() : collectionType.values().stream(); 1031 Stream<Class<?>> at = associationType == null ? Stream.empty() : associationType.values().stream(); 1032 1033 Stream<String> nestedColumns = Stream.concat(at, ct) 1034 .map(TableInfoFactory::ofEntityClass) 1035 .flatMap(e -> Arrays.stream(e.allColumns)); 1036 1037 // 预加载所有重复列,用于判断重名属性 1038 List<String> existedColumns = Stream.concat(Arrays.stream(allColumns), nestedColumns) 1039 .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) 1040 .entrySet() 1041 .stream() 1042 .filter(e -> e.getValue().intValue() > 1) 1043 .map(Map.Entry::getKey) 1044 .collect(Collectors.toList()); 1045 1046 return doBuildResultMap(configuration, new HashSet<>(), existedColumns, false, getTableNameWithSchema()); 1047 } 1048 1049 private ResultMap doBuildResultMap(Configuration configuration, Set<String> resultMapIds, List<String> existedColumns, boolean isNested, String nestedPrefix) { 1050 1051 String resultMapId = isNested ? "nested-" + nestedPrefix + ":" + entityClass.getName() : entityClass.getName(); 1052 1053 // 是否有循环引用 1054 boolean withCircularReference = resultMapIds.contains(resultMapId) || resultMapIds.contains(entityClass.getName()); 1055 if (withCircularReference) { 1056 return null; 1057 } 1058 1059 resultMapIds.add(resultMapId); 1060 1061 if (configuration.hasResultMap(resultMapId)) { 1062 return configuration.getResultMap(resultMapId); 1063 } 1064 1065 List<ResultMapping> resultMappings = new ArrayList<>(); 1066 1067 // <resultMap> 标签下的 <id> 标签映射 1068 for (IdInfo idInfo : primaryKeyList) { 1069 doBuildColumnResultMapping(configuration, resultMappings, existedColumns, idInfo, CollectionUtil.newArrayList(ResultFlag.ID), isNested); 1070 } 1071 1072 // <resultMap> 标签下的 <result> 标签映射 1073 for (ColumnInfo columnInfo : columnInfoList) { 1074 doBuildColumnResultMapping(configuration, resultMappings, existedColumns, columnInfo, Collections.emptyList(), isNested); 1075 } 1076 1077 // <resultMap> 标签下的 <association> 标签映射 1078 if (associationType != null) { 1079 associationType.forEach((fieldName, fieldType) -> { 1080 // 获取嵌套类型的信息,也就是 javaType 属性 1081 TableInfo tableInfo = TableInfoFactory.ofEntityClass(fieldType); 1082 // 构建嵌套类型的 ResultMap 对象,也就是 <association> 标签下的内容 1083 ResultMap nestedResultMap = tableInfo.doBuildResultMap(configuration, resultMapIds, existedColumns, true, nestedPrefix); 1084 if (nestedResultMap != null) { 1085 resultMappings.add(new ResultMapping.Builder(configuration, fieldName) 1086 .javaType(fieldType) 1087 .nestedResultMapId(nestedResultMap.getId()) 1088 .build()); 1089 } 1090 }); 1091 } 1092 1093 // <resultMap> 标签下的 <collection> 标签映射 1094 if (collectionType != null) { 1095 collectionType.forEach((field, genericClass) -> { 1096 if (TableInfoFactory.defaultSupportColumnTypes.contains(genericClass)) { 1097 // List<String> List<Integer> 等 1098 String columnName = TableInfoFactory.getColumnName(camelToUnderline, field, field.getAnnotation(Column.class)); 1099 // 映射 <result column="..."/> 1100 ResultMapping resultMapping = new ResultMapping.Builder(configuration, null) 1101 .column(columnName) 1102 .typeHandler(configuration.getTypeHandlerRegistry().getTypeHandler(genericClass)) 1103 .build(); 1104 String nestedResultMapId = entityClass.getName() + "." + field.getName(); 1105 ResultMap nestedResultMap; 1106 if (configuration.hasResultMap(nestedResultMapId)) { 1107 nestedResultMap = configuration.getResultMap(nestedResultMapId); 1108 } else { 1109 nestedResultMap = new ResultMap.Builder(configuration, nestedResultMapId, genericClass, Collections.singletonList(resultMapping)).build(); 1110 configuration.addResultMap(nestedResultMap); 1111 } 1112 // 映射 <collection property="..." ofType="genericClass"> 1113 resultMappings.add(new ResultMapping.Builder(configuration, field.getName()) 1114 .javaType(field.getType()) 1115 .nestedResultMapId(nestedResultMap.getId()) 1116 .build()); 1117 } else { 1118 // 获取集合泛型类型的信息,也就是 ofType 属性 1119 TableInfo tableInfo = TableInfoFactory.ofEntityClass(genericClass); 1120 // 构建嵌套类型的 ResultMap 对象,也就是 <collection> 标签下的内容 1121 ResultMap nestedResultMap = tableInfo.doBuildResultMap(configuration, resultMapIds, existedColumns, true, nestedPrefix); 1122 if (nestedResultMap != null) { 1123 resultMappings.add(new ResultMapping.Builder(configuration, field.getName()) 1124 .javaType(field.getType()) 1125 .nestedResultMapId(nestedResultMap.getId()) 1126 .build()); 1127 } 1128 } 1129 }); 1130 } 1131 1132 ResultMap resultMap = new ResultMap.Builder(configuration, resultMapId, entityClass, resultMappings).build(); 1133 configuration.addResultMap(resultMap); 1134 resultMapIds.add(resultMapId); 1135 return resultMap; 1136 } 1137 1138 private void doBuildColumnResultMapping(Configuration configuration, List<ResultMapping> resultMappings 1139 , List<String> existedColumns, ColumnInfo columnInfo, List<ResultFlag> flags, boolean isNested) { 1140 1141 if (!isNested) { 1142 if (existedColumns.contains(columnInfo.column)) { 1143 // userName -> tb_user$user_name 1144 resultMappings.add(new ResultMapping.Builder(configuration 1145 , columnInfo.property 1146 , tableName + "$" + columnInfo.column 1147 , columnInfo.propertyType) 1148 .jdbcType(columnInfo.getJdbcType()) 1149 .flags(flags) 1150 .typeHandler(columnInfo.buildTypeHandler(configuration)) 1151 .build()); 1152 } 1153 buildDefaultResultMapping(configuration, resultMappings, columnInfo, flags); 1154 } else { 1155 if (existedColumns.contains(columnInfo.column)) { 1156 // userName -> tb_user$user_name 1157 resultMappings.add(new ResultMapping.Builder(configuration 1158 , columnInfo.property 1159 , tableName + "$" + columnInfo.column 1160 , columnInfo.propertyType) 1161 .jdbcType(columnInfo.getJdbcType()) 1162 .flags(flags) 1163 .typeHandler(columnInfo.buildTypeHandler(configuration)) 1164 .build()); 1165 } else { 1166 buildDefaultResultMapping(configuration, resultMappings, columnInfo, flags); 1167 } 1168 } 1169 1170 if (ArrayUtil.isNotEmpty(columnInfo.alias)) { 1171 for (String alias : columnInfo.alias) { 1172 // userName -> alias 1173 resultMappings.add(new ResultMapping.Builder(configuration 1174 , columnInfo.property 1175 , alias 1176 , columnInfo.propertyType) 1177 .jdbcType(columnInfo.getJdbcType()) 1178 .flags(flags) 1179 .typeHandler(columnInfo.buildTypeHandler(configuration)) 1180 .build()); 1181 } 1182 } 1183 1184 } 1185 1186 private void buildDefaultResultMapping(Configuration configuration, List<ResultMapping> resultMappings, ColumnInfo columnInfo, List<ResultFlag> flags) { 1187 // userName -> user_name 1188 resultMappings.add(new ResultMapping.Builder(configuration 1189 , columnInfo.property 1190 , columnInfo.column 1191 , columnInfo.propertyType) 1192 .jdbcType(columnInfo.getJdbcType()) 1193 .flags(flags) 1194 .typeHandler(columnInfo.buildTypeHandler(configuration)) 1195 .build()); 1196 1197 if (!Objects.equals(columnInfo.column, columnInfo.property)) { 1198 // userName -> userName 1199 resultMappings.add(new ResultMapping.Builder(configuration 1200 , columnInfo.property 1201 , columnInfo.property 1202 , columnInfo.propertyType) 1203 .jdbcType(columnInfo.getJdbcType()) 1204 .flags(flags) 1205 .typeHandler(columnInfo.buildTypeHandler(configuration)) 1206 .build()); 1207 } 1208 } 1209 1210 1211 private Object buildColumnSqlArg(MetaObject metaObject, String column) { 1212 ColumnInfo columnInfo = columnInfoMapping.get(column); 1213 Object value = getPropertyValue(metaObject, columnInfo.property); 1214 if (value != null) { 1215 TypeHandler<?> typeHandler = columnInfo.buildTypeHandler(null); 1216 if (typeHandler != null) { 1217 return new TypeHandlerObject(typeHandler, value, columnInfo.getJdbcType()); 1218 } 1219 } 1220 return value; 1221 } 1222 1223 1224 public Object buildColumnSqlArg(Object entityObject, String column) { 1225 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 1226 return buildColumnSqlArg(metaObject, column); 1227 } 1228 1229 1230 public Object getPropertyValue(MetaObject metaObject, String property) { 1231 if (property != null && metaObject.hasGetter(property)) { 1232 return metaObject.getValue(property); 1233 } 1234 return null; 1235 } 1236 1237 1238 /** 1239 * 通过 row 实例类转换为一个 entity 1240 * 1241 * @return entity 1242 */ 1243 public <T> T newInstanceByRow(Row row, int index) { 1244 Object instance = ClassUtil.newInstance(entityClass); 1245 MetaObject metaObject = EntityMetaObject.forObject(instance, reflectorFactory); 1246 Set<String> rowKeys = row.keySet(); 1247 columnInfoMapping.forEach((column, columnInfo) -> { 1248 if (index <= 0) { 1249 String replace = column.replace("_", ""); 1250 for (String rowKey : rowKeys) { 1251 // 修复: 开启 mapUnderscoreToCamelCase = true 时, row 无法转换 entity 的问题 1252 if (rowKey.equalsIgnoreCase(column) || rowKey.equalsIgnoreCase(replace)) { 1253 setInstancePropertyValue(row, instance, metaObject, columnInfo, rowKey); 1254 } 1255 } 1256 } else { 1257 for (int i = index; i >= 0; i--) { 1258 String newColumn = i <= 0 ? column : column + "$" + i; 1259 boolean fillValue = false; 1260 String replace = column.replace("_", ""); 1261 for (String rowKey : rowKeys) { 1262 // 修复: 开启 mapUnderscoreToCamelCase = true 时, row 无法转换 entity 的问题 1263 if (rowKey.equalsIgnoreCase(newColumn) || rowKey.equalsIgnoreCase(replace)) { 1264 setInstancePropertyValue(row, instance, metaObject, columnInfo, rowKey); 1265 fillValue = true; 1266 break; 1267 } 1268 } 1269 if (fillValue) { 1270 break; 1271 } 1272 } 1273 } 1274 }); 1275 //noinspection unchecked 1276 return (T) instance; 1277 } 1278 1279 1280 private void setInstancePropertyValue(Row row, Object instance, MetaObject metaObject, ColumnInfo columnInfo, String rowKey) { 1281 Object rowValue = row.get(rowKey); 1282 TypeHandler<?> typeHandler = columnInfo.buildTypeHandler(null); 1283 if (typeHandler != null) { 1284 try { 1285 //通过 typeHandler 转换数据 1286 rowValue = typeHandler.getResult(getResultSet(rowValue), 0); 1287 } catch (SQLException e) { 1288 //ignore 1289 } 1290 } 1291 if (rowValue != null && !metaObject.getSetterType(columnInfo.property).isAssignableFrom(rowValue.getClass())) { 1292 rowValue = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property), true); 1293 } 1294 rowValue = invokeOnSetListener(instance, columnInfo.property, rowValue); 1295 metaObject.setValue(columnInfo.property, rowValue); 1296 } 1297 1298 1299 private ResultSet getResultSet(Object value) { 1300 return (ResultSet) Proxy.newProxyInstance(TableInfo.class.getClassLoader(), 1301 new Class[]{ResultSet.class}, (proxy, method, args) -> value); 1302 } 1303 1304 1305 /** 1306 * 初始化乐观锁版本号 1307 * 1308 * @param entityObject 1309 */ 1310 public void initVersionValueIfNecessary(Object entityObject) { 1311 if (StringUtil.isBlank(versionColumn)) { 1312 return; 1313 } 1314 1315 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 1316 Object columnValue = getPropertyValue(metaObject, columnInfoMapping.get(versionColumn).property); 1317 if (columnValue == null) { 1318 String name = columnInfoMapping.get(versionColumn).property; 1319 Class<?> clazz = metaObject.getSetterType(name); 1320 metaObject.setValue(name, ConvertUtil.convert(0L, clazz)); 1321 } 1322 } 1323 1324 /** 1325 * 设置租户id 1326 * 1327 * @param entityObject 1328 */ 1329 public void initTenantIdIfNecessary(Object entityObject) { 1330 if (StringUtil.isBlank(tenantIdColumn)) { 1331 return; 1332 } 1333 1334 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 1335 Object[] tenantIds = TenantManager.getTenantIds(); 1336 if (tenantIds == null || tenantIds.length == 0) { 1337 return; 1338 } 1339 1340 //默认使用第一个作为插入的租户ID 1341 Object tenantId = tenantIds[0]; 1342 if (tenantId != null) { 1343 String property = columnInfoMapping.get(tenantIdColumn).property; 1344 Class<?> setterType = metaObject.getSetterType(property); 1345 metaObject.setValue(property, ConvertUtil.convert(tenantId, setterType)); 1346 } 1347 } 1348 1349 /** 1350 * 初始化逻辑删除的默认值 1351 * 1352 * @param entityObject 1353 */ 1354 public void initLogicDeleteValueIfNecessary(Object entityObject) { 1355 if (StringUtil.isBlank(getLogicDeleteColumnOrSkip())) { 1356 return; 1357 } 1358 1359 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 1360 ColumnInfo logicDeleteColumn = columnInfoMapping.get(this.logicDeleteColumn); 1361 Object columnValue = getPropertyValue(metaObject, logicDeleteColumn.property); 1362 if (columnValue == null) { 1363 Object normalValueOfLogicDelete = LogicDeleteManager.getProcessor().getLogicNormalValue(); 1364 if (normalValueOfLogicDelete != null) { 1365 String property = logicDeleteColumn.property; 1366 Class<?> setterType = metaObject.getSetterType(property); 1367 metaObject.setValue(property, ConvertUtil.convert(normalValueOfLogicDelete, setterType)); 1368 } 1369 } 1370 } 1371 1372 1373 private static final Map<Class<?>, List<InsertListener>> insertListenerCache = new ConcurrentHashMap<>(); 1374 1375 public void invokeOnInsertListener(Object entity) { 1376 List<InsertListener> listeners = MapUtil.computeIfAbsent(insertListenerCache, entityClass, aClass -> { 1377 List<InsertListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 1378 .getSupportedInsertListener(entityClass); 1379 List<InsertListener> allListeners = CollectionUtil.merge(onInsertListeners, globalListeners); 1380 Collections.sort(allListeners); 1381 return allListeners; 1382 }); 1383 listeners.forEach(insertListener -> insertListener.onInsert(entity)); 1384 } 1385 1386 1387 private static final Map<Class<?>, List<UpdateListener>> updateListenerCache = new ConcurrentHashMap<>(); 1388 1389 public void invokeOnUpdateListener(Object entity) { 1390 List<UpdateListener> listeners = MapUtil.computeIfAbsent(updateListenerCache, entityClass, aClass -> { 1391 List<UpdateListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 1392 .getSupportedUpdateListener(entityClass); 1393 List<UpdateListener> allListeners = CollectionUtil.merge(onUpdateListeners, globalListeners); 1394 Collections.sort(allListeners); 1395 return allListeners; 1396 }); 1397 listeners.forEach(insertListener -> insertListener.onUpdate(entity)); 1398 } 1399 1400 1401 private static final Map<Class<?>, List<SetListener>> setListenerCache = new ConcurrentHashMap<>(); 1402 1403 public Object invokeOnSetListener(Object entity, String property, Object value) { 1404 List<SetListener> listeners = MapUtil.computeIfAbsent(setListenerCache, entityClass, aClass -> { 1405 List<SetListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 1406 .getSupportedSetListener(entityClass); 1407 List<SetListener> allListeners = CollectionUtil.merge(onSetListeners, globalListeners); 1408 Collections.sort(allListeners); 1409 return allListeners; 1410 }); 1411 for (SetListener setListener : listeners) { 1412 value = setListener.onSet(entity, property, value); 1413 } 1414 return value; 1415 } 1416 1417 public QueryColumn getQueryColumnByProperty(String property) { 1418 String column = getColumnByProperty(property); 1419 return columnQueryMapping.get(column); 1420 } 1421 1422}