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.InsertListener; 019import com.mybatisflex.annotation.KeyType; 020import com.mybatisflex.annotation.SetListener; 021import com.mybatisflex.annotation.UpdateListener; 022import com.mybatisflex.core.FlexConsts; 023import com.mybatisflex.core.FlexGlobalConfig; 024import com.mybatisflex.core.exception.FlexExceptions; 025import com.mybatisflex.core.javassist.ModifyAttrsRecord; 026import com.mybatisflex.core.mybatis.TypeHandlerObject; 027import com.mybatisflex.core.query.*; 028import com.mybatisflex.core.row.Row; 029import com.mybatisflex.core.tenant.TenantManager; 030import com.mybatisflex.core.util.*; 031import org.apache.ibatis.mapping.ResultFlag; 032import org.apache.ibatis.mapping.ResultMap; 033import org.apache.ibatis.mapping.ResultMapping; 034import org.apache.ibatis.reflection.MetaObject; 035import org.apache.ibatis.reflection.Reflector; 036import org.apache.ibatis.reflection.ReflectorFactory; 037import org.apache.ibatis.session.Configuration; 038import org.apache.ibatis.type.TypeHandler; 039import org.apache.ibatis.util.MapUtil; 040 041import java.lang.reflect.Proxy; 042import java.sql.ResultSet; 043import java.sql.SQLException; 044import java.util.*; 045import java.util.concurrent.ConcurrentHashMap; 046import java.util.stream.Collectors; 047 048public class TableInfo { 049 050 private String schema; //schema 051 private String tableName; //表名 052 private Class<?> entityClass; //实体类 053 private boolean camelToUnderline = true; 054 private String dataSource; 055 056 //逻辑删除数据库列名 057 private String logicDeleteColumn; 058 059 //乐观锁字段 060 private String versionColumn; 061 062 //租户ID 字段 063 private String tenantIdColumn; 064 065 //数据插入时,默认插入数据字段 066 private Map<String, String> onInsertColumns; 067 068 //数据更新时,默认更新内容的字段 069 private Map<String, String> onUpdateColumns; 070 071 //大字段列 072 private String[] largeColumns = new String[0]; 073 074 // 所有的字段,但除了主键的列 075 private String[] columns = new String[0]; 076 077 //主键字段 078 private String[] primaryKeys = new String[0]; 079 080 // 默认查询列 081 private String[] defaultColumns = new String[0]; 082 083 //在插入数据的时候,支持主动插入的主键字段 084 //通过自定义生成器生成 或者 Sequence 在 before 生成的时候,是需要主动插入数据的 085 private String[] insertPrimaryKeys; 086 087 private List<ColumnInfo> columnInfoList; 088 private List<IdInfo> primaryKeyList; 089 090 //column 和 java 属性的称的关系映射 091 private Map<String, ColumnInfo> columnInfoMapping = new HashMap<>(); 092 private Map<String, String> propertyColumnMapping = new HashMap<>(); 093 094 private List<InsertListener> onInsertListeners; 095 private List<UpdateListener> onUpdateListeners; 096 private List<SetListener> onSetListeners; 097 098 099 private final ReflectorFactory reflectorFactory = new BaseReflectorFactory() { 100 @Override 101 public Reflector findForClass(Class<?> type) { 102 return getReflector(); 103 } 104 }; 105 private Reflector reflector; //反射工具 106 107 public String getSchema() { 108 return schema; 109 } 110 111 public void setSchema(String schema) { 112 this.schema = schema; 113 } 114 115 public String getTableName() { 116 return tableName; 117 } 118 119 public void setTableName(String tableName) { 120 this.tableName = tableName; 121 } 122 123 public Class<?> getEntityClass() { 124 return entityClass; 125 } 126 127 public void setEntityClass(Class<?> entityClass) { 128 this.entityClass = entityClass; 129 } 130 131 public boolean isCamelToUnderline() { 132 return camelToUnderline; 133 } 134 135 public void setCamelToUnderline(boolean camelToUnderline) { 136 this.camelToUnderline = camelToUnderline; 137 } 138 139 public String getDataSource() { 140 return dataSource; 141 } 142 143 public void setDataSource(String dataSource) { 144 this.dataSource = dataSource; 145 } 146 147 public String getLogicDeleteColumn() { 148 return logicDeleteColumn; 149 } 150 151 public void setLogicDeleteColumn(String logicDeleteColumn) { 152 this.logicDeleteColumn = logicDeleteColumn; 153 } 154 155 public String getVersionColumn() { 156 return versionColumn; 157 } 158 159 public void setVersionColumn(String versionColumn) { 160 this.versionColumn = versionColumn; 161 } 162 163 public String getTenantIdColumn() { 164 return tenantIdColumn; 165 } 166 167 public void setTenantIdColumn(String tenantIdColumn) { 168 this.tenantIdColumn = tenantIdColumn; 169 } 170 171 public Map<String, String> getOnInsertColumns() { 172 return onInsertColumns; 173 } 174 175 public void setOnInsertColumns(Map<String, String> onInsertColumns) { 176 this.onInsertColumns = onInsertColumns; 177 } 178 179 public Map<String, String> getOnUpdateColumns() { 180 return onUpdateColumns; 181 } 182 183 public void setOnUpdateColumns(Map<String, String> onUpdateColumns) { 184 this.onUpdateColumns = onUpdateColumns; 185 } 186 187 public String[] getLargeColumns() { 188 return largeColumns; 189 } 190 191 public void setLargeColumns(String[] largeColumns) { 192 this.largeColumns = largeColumns; 193 } 194 195 public String[] getDefaultColumns() { 196 return defaultColumns; 197 } 198 199 public void setDefaultColumns(String[] defaultColumns) { 200 this.defaultColumns = defaultColumns; 201 } 202 203 public String[] getInsertPrimaryKeys() { 204 return insertPrimaryKeys; 205 } 206 207 public void setInsertPrimaryKeys(String[] insertPrimaryKeys) { 208 this.insertPrimaryKeys = insertPrimaryKeys; 209 } 210 211 public Reflector getReflector() { 212 return reflector; 213 } 214 215 public ReflectorFactory getReflectorFactory() { 216 return reflectorFactory; 217 } 218 219 public void setReflector(Reflector reflector) { 220 this.reflector = reflector; 221 } 222 223 public String[] getColumns() { 224 return columns; 225 } 226 227 228 public void setColumns(String[] columns) { 229 this.columns = columns; 230 } 231 232 public String[] getPrimaryKeys() { 233 return primaryKeys; 234 } 235 236 public void setPrimaryKeys(String[] primaryKeys) { 237 this.primaryKeys = primaryKeys; 238 } 239 240 241 public List<InsertListener> getOnInsertListeners() { 242 return onInsertListeners; 243 } 244 245 public void setOnInsertListeners(List<InsertListener> onInsertListeners) { 246 this.onInsertListeners = onInsertListeners; 247 } 248 249 public List<UpdateListener> getOnUpdateListeners() { 250 return onUpdateListeners; 251 } 252 253 public void setOnUpdateListeners(List<UpdateListener> onUpdateListeners) { 254 this.onUpdateListeners = onUpdateListeners; 255 } 256 257 public List<SetListener> getOnSetListeners() { 258 return onSetListeners; 259 } 260 261 public void setOnSetListeners(List<SetListener> onSetListeners) { 262 this.onSetListeners = onSetListeners; 263 } 264 265 public List<ColumnInfo> getColumnInfoList() { 266 return columnInfoList; 267 } 268 269 270 void setColumnInfoList(List<ColumnInfo> columnInfoList) { 271 this.columnInfoList = columnInfoList; 272 this.columns = new String[columnInfoList.size()]; 273 for (int i = 0; i < columnInfoList.size(); i++) { 274 ColumnInfo columnInfo = columnInfoList.get(i); 275 columns[i] = columnInfo.getColumn(); 276 columnInfoMapping.put(columnInfo.column, columnInfo); 277 propertyColumnMapping.put(columnInfo.property, columnInfo.column); 278 } 279 } 280 281 282 public List<IdInfo> getPrimaryKeyList() { 283 return primaryKeyList; 284 } 285 286 void setPrimaryKeyList(List<IdInfo> primaryKeyList) { 287 this.primaryKeyList = primaryKeyList; 288 this.primaryKeys = new String[primaryKeyList.size()]; 289 290 List<String> insertIdFields = new ArrayList<>(); 291 for (int i = 0; i < primaryKeyList.size(); i++) { 292 IdInfo idInfo = primaryKeyList.get(i); 293 primaryKeys[i] = idInfo.getColumn(); 294 295 if (idInfo.getKeyType() != KeyType.Auto && (idInfo.getBefore() != null && idInfo.getBefore())) { 296 insertIdFields.add(idInfo.getColumn()); 297 } 298 299 columnInfoMapping.put(idInfo.column, idInfo); 300 propertyColumnMapping.put(idInfo.property, idInfo.column); 301 } 302 this.insertPrimaryKeys = insertIdFields.toArray(new String[0]); 303 } 304 305 306 /** 307 * 插入(新增)数据时,获取所有要插入的字段 308 * 309 * @param entity 310 * @param ignoreNulls 311 * @return 字段列表 312 */ 313 public String[] obtainInsertColumns(Object entity, boolean ignoreNulls) { 314 if (!ignoreNulls) { 315 return ArrayUtil.concat(insertPrimaryKeys, columns); 316 } else { 317 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 318 List<String> retColumns = new ArrayList<>(); 319 for (String insertColumn : columns) { 320 if (onInsertColumns != null && onInsertColumns.containsKey(insertColumn)) { 321 retColumns.add(insertColumn); 322 } else { 323 Object value = buildColumnSqlArg(metaObject, insertColumn); 324 if (value == null) { 325 continue; 326 } 327 retColumns.add(insertColumn); 328 } 329 } 330 return ArrayUtil.concat(insertPrimaryKeys, retColumns.toArray(new String[0])); 331 } 332 } 333 334 335 /** 336 * 构建 insert 的 Sql 参数 337 * 338 * @param entity 从 entity 中获取 339 * @param ignoreNulls 是否忽略 null 值 340 * @return 数组 341 */ 342 public Object[] buildInsertSqlArgs(Object entity, boolean ignoreNulls) { 343 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 344 String[] insertColumns = obtainInsertColumns(entity, ignoreNulls); 345 346 List<Object> values = new ArrayList<>(insertColumns.length); 347 for (String insertColumn : insertColumns) { 348 if (onInsertColumns == null || !onInsertColumns.containsKey(insertColumn)) { 349 Object value = buildColumnSqlArg(metaObject, insertColumn); 350 if (ignoreNulls && value == null) { 351 continue; 352 } 353 values.add(value); 354 } 355 } 356 return values.toArray(); 357 } 358 359 360 /** 361 * 获取要修改的值 362 * 363 * @param entity 364 * @param ignoreNulls 365 */ 366 public Set<String> obtainUpdateColumns(Object entity, boolean ignoreNulls, boolean includePrimary) { 367 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 368 Set<String> columns = new LinkedHashSet<>(); //需使用 LinkedHashSet 保证 columns 的顺序 369 if (entity instanceof ModifyAttrsRecord) { 370 Set<String> properties = ((ModifyAttrsRecord) entity).obtainModifyAttrs(); 371 if (properties.isEmpty()) { 372 return Collections.emptySet(); 373 } 374 for (String property : properties) { 375 String column = propertyColumnMapping.get(property); 376 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 377 continue; 378 } 379 380 //过滤乐观锁字段 和 租户字段 381 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 382 continue; 383 } 384 385 if (!includePrimary && ArrayUtil.contains(primaryKeys, column)) { 386 continue; 387 } 388 389 // ModifyAttrsRecord 忽略 ignoreNulls 的设置 390 // Object value = getPropertyValue(metaObject, property); 391 // if (ignoreNulls && value == null) { 392 // continue; 393 // } 394 columns.add(column); 395 } 396 } 397 //not ModifyAttrsRecord 398 else { 399 for (String column : this.columns) { 400 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 401 continue; 402 } 403 404 //过滤乐观锁字段 和 租户字段 405 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 406 continue; 407 } 408 409 Object value = buildColumnSqlArg(metaObject, column); 410 if (ignoreNulls && value == null) { 411 continue; 412 } 413 414 columns.add(column); 415 } 416 417 // 普通 entity(非 ModifyAttrsRecord) 忽略 includePrimary 的设置 418// if (includePrimary) { 419// for (String column : this.primaryKeys) { 420// Object value = getColumnValue(metaObject, column); 421// if (ignoreNulls && value == null) { 422// continue; 423// } 424// columns.add(column); 425// } 426// } 427 } 428 return columns; 429 } 430 431 /** 432 * 获取所有要修改的值,默认为全部除了主键以外的字段 433 * 434 * @param entity 实体对象 435 * @return 数组 436 */ 437 public Object[] buildUpdateSqlArgs(Object entity, boolean ignoreNulls, boolean includePrimary) { 438 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 439 List<Object> values = new ArrayList<>(); 440 if (entity instanceof ModifyAttrsRecord) { 441 Set<String> properties = ((ModifyAttrsRecord) entity).obtainModifyAttrs(); 442 if (properties.isEmpty()) { 443 return values.toArray(); 444 } 445 for (String property : properties) { 446 String column = propertyColumnMapping.get(property); 447 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 448 continue; 449 } 450 //过滤乐观锁字段 和 租户字段 451 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 452 continue; 453 } 454 455 if (!includePrimary && ArrayUtil.contains(primaryKeys, column)) { 456 continue; 457 } 458 459 Object value = getPropertyValue(metaObject, property); 460 461 // ModifyAttrsRecord 忽略 ignoreNulls 的设置, 462 // 当使用 ModifyAttrsRecord 时,可以理解为要对字段进行 null 值进行更新,否则没必要使用 ModifyAttrsRecord 463 // if (ignoreNulls && value == null) { 464 // continue; 465 // } 466 values.add(value); 467 } 468 } 469 // normal entity. not ModifyAttrsRecord 470 else { 471 for (String column : this.columns) { 472 if (onUpdateColumns != null && onUpdateColumns.containsKey(column)) { 473 continue; 474 } 475 476 //过滤乐观锁字段 和 租户字段 477 if (ObjectUtil.equalsAny(column, versionColumn, tenantIdColumn)) { 478 continue; 479 } 480 481 // 普通 entity 忽略 includePrimary 的设置, 482 // 因为 for 循环中的 this.columns 本身就不包含有主键 483 // if (includePrimary) { 484 // } 485 486 Object value = buildColumnSqlArg(metaObject, column); 487 if (ignoreNulls && value == null) { 488 continue; 489 } 490 491 values.add(value); 492 } 493 } 494 495 return values.toArray(); 496 } 497 498 499 /** 500 * 构建主键的 sql 参数数据 501 * 502 * @param entity 503 */ 504 public Object[] buildPkSqlArgs(Object entity) { 505 MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory); 506 Object[] values = new Object[primaryKeys.length]; 507 for (int i = 0; i < primaryKeys.length; i++) { 508 values[i] = buildColumnSqlArg(metaObject, primaryKeys[i]); 509 } 510 return values; 511 } 512 513 514 public Object[] buildTenantIdArgs() { 515 if (StringUtil.isBlank(tenantIdColumn)) { 516 return null; 517 } 518 519 return TenantManager.getTenantIds(); 520 } 521 522 private static final String APPEND_CONDITIONS_FLAG = "appendConditions"; 523 524 public void appendConditions(Object entity, QueryWrapper queryWrapper) { 525 526 Object appendConditions = CPI.getContext(queryWrapper, APPEND_CONDITIONS_FLAG); 527 if (Boolean.TRUE.equals(appendConditions)) { 528 return; 529 } else { 530 CPI.putContext(queryWrapper, APPEND_CONDITIONS_FLAG, Boolean.TRUE); 531 } 532 533 //select * from (select ... from ) 中的子查询处理 534 List<QueryTable> queryTables = CPI.getQueryTables(queryWrapper); 535 if (queryTables != null && !queryTables.isEmpty()) { 536 for (QueryTable queryTable : queryTables) { 537 if (queryTable instanceof SelectQueryTable) { 538 QueryWrapper selectQueryWrapper = ((SelectQueryTable) queryTable).getQueryWrapper(); 539 List<QueryTable> selectQueryTables = CPI.getQueryTables(selectQueryWrapper); 540 if (selectQueryTables != null && !selectQueryTables.isEmpty()) { 541 for (QueryTable selectQueryTable : selectQueryTables) { 542 TableInfo tableInfo = TableInfoFactory.ofTableName(selectQueryTable.getName()); 543 if (tableInfo != null) { 544 tableInfo.appendConditions(entity, selectQueryWrapper); 545 } 546 } 547 } 548 } 549 } 550 } 551 552 //添加乐观锁条件,只有在 update 的时候进行处理 553 if (StringUtil.isNotBlank(versionColumn) && entity != null) { 554 Object versionValue = buildColumnSqlArg(entity, versionColumn); 555 if (versionValue == null) { 556 throw FlexExceptions.wrap("The version value of entity[%s] must not be null.", entity); 557 } 558 queryWrapper.and(QueryCondition.create(tableName, versionColumn, QueryCondition.LOGIC_EQUALS, versionValue)); 559 } 560 561 //逻辑删除 562 if (StringUtil.isNotBlank(logicDeleteColumn)) { 563 queryWrapper.and(QueryCondition.create(tableName, logicDeleteColumn, QueryCondition.LOGIC_EQUALS 564 , FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete())); 565 } 566 567 //多租户 568 Object[] tenantIdArgs = buildTenantIdArgs(); 569 if (ArrayUtil.isNotEmpty(tenantIdArgs)) { 570 if (tenantIdArgs.length == 1) { 571 queryWrapper.and(QueryCondition.create(tableName, tenantIdColumn, QueryCondition.LOGIC_EQUALS, tenantIdArgs[0])); 572 } else { 573 queryWrapper.and(QueryCondition.create(tableName, tenantIdColumn, QueryCondition.LOGIC_IN, tenantIdArgs)); 574 } 575 } 576 577 //子查询 578 List<QueryWrapper> childSelects = CPI.getChildSelect(queryWrapper); 579 if (CollectionUtil.isNotEmpty(childSelects)) { 580 for (QueryWrapper childQueryWrapper : childSelects) { 581 List<QueryTable> childQueryTables = CPI.getQueryTables(childQueryWrapper); 582 for (QueryTable queryTable : childQueryTables) { 583 TableInfo tableInfo = TableInfoFactory.ofTableName(queryTable.getName()); 584 if (tableInfo != null) { 585 tableInfo.appendConditions(entity, childQueryWrapper); 586 } 587 } 588 } 589 } 590 591 //union 592 List<UnionWrapper> unions = CPI.getUnions(queryWrapper); 593 if (CollectionUtil.isNotEmpty(unions)) { 594 for (UnionWrapper union : unions) { 595 QueryWrapper unionQueryWrapper = union.getQueryWrapper(); 596 List<QueryTable> unionQueryTables = CPI.getQueryTables(unionQueryWrapper); 597 for (QueryTable queryTable : unionQueryTables) { 598 TableInfo tableInfo = TableInfoFactory.ofTableName(queryTable.getName()); 599 if (tableInfo != null) { 600 tableInfo.appendConditions(entity, unionQueryWrapper); 601 } 602 } 603 } 604 } 605 606 } 607 608 609 public String getKeyProperties() { 610 StringJoiner joiner = new StringJoiner(","); 611 for (IdInfo value : primaryKeyList) { 612 joiner.add(FlexConsts.ENTITY + "." + value.getProperty()); 613 } 614 return joiner.toString(); 615 } 616 617 618 public String getKeyColumns() { 619 StringJoiner joiner = new StringJoiner(","); 620 for (IdInfo value : primaryKeyList) { 621 joiner.add(value.getColumn()); 622 } 623 return joiner.toString(); 624 } 625 626 public List<QueryColumn> getDefaultQueryColumn() { 627 return Arrays.stream(defaultColumns) 628 .map(name -> new QueryColumn(getTableName(), name)) 629 .collect(Collectors.toList()); 630 } 631 632 public ResultMap buildResultMap(Configuration configuration) { 633 String resultMapId = entityClass.getName(); 634 List<ResultMapping> resultMappings = new ArrayList<>(); 635 636 for (ColumnInfo columnInfo : columnInfoList) { 637 ResultMapping mapping = new ResultMapping.Builder(configuration, columnInfo.getProperty(), 638 columnInfo.getColumn(), columnInfo.getPropertyType()) 639 .jdbcType(columnInfo.getJdbcType()) 640 .typeHandler(columnInfo.buildTypeHandler()) 641 .build(); 642 resultMappings.add(mapping); 643 } 644 645 for (IdInfo idInfo : primaryKeyList) { 646 ResultMapping mapping = new ResultMapping.Builder(configuration, idInfo.getProperty(), 647 idInfo.getColumn(), idInfo.getPropertyType()) 648 .flags(CollectionUtil.newArrayList(ResultFlag.ID)) 649 .jdbcType(idInfo.getJdbcType()) 650 .typeHandler(idInfo.buildTypeHandler()) 651 .build(); 652 resultMappings.add(mapping); 653 } 654 655 return new ResultMap.Builder(configuration, resultMapId, entityClass, resultMappings).build(); 656 } 657 658 659 private Object buildColumnSqlArg(MetaObject metaObject, String column) { 660 ColumnInfo columnInfo = columnInfoMapping.get(column); 661 Object value = getPropertyValue(metaObject, columnInfo.property); 662 663 TypeHandler typeHandler = columnInfo.buildTypeHandler(); 664 if (value != null && typeHandler != null) { 665 return new TypeHandlerObject(typeHandler, value, columnInfo.getJdbcType()); 666 } 667 668 return value; 669 } 670 671 672 public Object buildColumnSqlArg(Object entityObject, String column) { 673 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 674 return buildColumnSqlArg(metaObject, column); 675 } 676 677 678 private Object getPropertyValue(MetaObject metaObject, String property) { 679 if (property != null && metaObject.hasGetter(property)) { 680 return metaObject.getValue(property); 681 } 682 return null; 683 } 684 685 686 /** 687 * 通过 row 实例类转换为一个 entity 688 * 689 * @return entity 690 */ 691 public <T> T newInstanceByRow(Row row, int index) { 692 Object instance = ClassUtil.newInstance(entityClass); 693 MetaObject metaObject = EntityMetaObject.forObject(instance, reflectorFactory); 694 Set<String> rowKeys = row.keySet(); 695 columnInfoMapping.forEach((column, columnInfo) -> { 696 if (index <= 0) { 697 for (String rowKey : rowKeys) { 698 if (column.equalsIgnoreCase(rowKey)) { 699 setInstancePropertyValue(row, instance, metaObject, columnInfo, rowKey); 700 } 701 } 702 } else { 703 for (int i = index; i >= 0; i--) { 704 String newColumn = i <= 0 ? column : column + "$" + i; 705 boolean fillValue = false; 706 for (String rowKey : rowKeys) { 707 if (newColumn.equalsIgnoreCase(rowKey)) { 708 setInstancePropertyValue(row, instance, metaObject, columnInfo, rowKey); 709 fillValue = true; 710 break; 711 } 712 } 713 if (fillValue) { 714 break; 715 } 716 } 717 } 718 }); 719 return (T) instance; 720 } 721 722 723 private void setInstancePropertyValue(Row row, Object instance, MetaObject metaObject, ColumnInfo columnInfo, String rowKey) { 724 Object rowValue = row.get(rowKey); 725 TypeHandler<?> typeHandler = columnInfo.buildTypeHandler(); 726 if (typeHandler != null) { 727 try { 728 //通过 typeHandler 转换数据 729 rowValue = typeHandler.getResult(getResultSet(rowValue), 0); 730 } catch (SQLException e) { 731 //ignore 732 } 733 } 734 if (rowValue != null && !metaObject.getSetterType(columnInfo.property).isAssignableFrom(rowValue.getClass())) { 735 rowValue = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property), true); 736 } 737 rowValue = invokeOnSetListener(instance, columnInfo.getProperty(), rowValue); 738 metaObject.setValue(columnInfo.property, rowValue); 739 } 740 741 742 private ResultSet getResultSet(Object value) { 743 return (ResultSet) Proxy.newProxyInstance(TableInfo.class.getClassLoader(), 744 new Class[]{ResultSet.class}, (proxy, method, args) -> value); 745 } 746 747 748 /** 749 * 初始化乐观锁版本号 750 * 751 * @param entityObject 752 */ 753 public void initVersionValueIfNecessary(Object entityObject) { 754 if (StringUtil.isBlank(versionColumn)) { 755 return; 756 } 757 758 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 759 Object columnValue = getPropertyValue(metaObject, columnInfoMapping.get(versionColumn).property); 760 if (columnValue == null) { 761 String name = columnInfoMapping.get(versionColumn).property; 762 Class<?> clazz = metaObject.getSetterType(name); 763 metaObject.setValue(name, ConvertUtil.convert(0L, clazz)); 764 } 765 } 766 767 /** 768 * 设置租户id 769 * 770 * @param entityObject 771 */ 772 public void initTenantIdIfNecessary(Object entityObject) { 773 if (StringUtil.isBlank(tenantIdColumn)) { 774 return; 775 } 776 777 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 778 Object[] tenantIds = TenantManager.getTenantIds(); 779 if (tenantIds == null || tenantIds.length == 0) { 780 return; 781 } 782 783 //默认使用第一个作为插入的租户ID 784 Object tenantId = tenantIds[0]; 785 if (tenantId != null) { 786 metaObject.setValue(columnInfoMapping.get(tenantIdColumn).property, tenantId); 787 } 788 } 789 790 /** 791 * 初始化逻辑删除的默认值 792 * 793 * @param entityObject 794 */ 795 public void initLogicDeleteValueIfNecessary(Object entityObject) { 796 if (StringUtil.isBlank(logicDeleteColumn)) { 797 return; 798 } 799 800 MetaObject metaObject = EntityMetaObject.forObject(entityObject, reflectorFactory); 801 Object columnValue = getPropertyValue(metaObject, columnInfoMapping.get(logicDeleteColumn).property); 802 if (columnValue == null) { 803 String property = columnInfoMapping.get(logicDeleteColumn).property; 804 Class<?> setterType = metaObject.getSetterType(property); 805 806 Object normalValueOfLogicDelete = FlexGlobalConfig.getDefaultConfig().getNormalValueOfLogicDelete(); 807 metaObject.setValue(property, ConvertUtil.convert(normalValueOfLogicDelete, setterType)); 808 } 809 } 810 811 812 private static Map<Class<?>, List<InsertListener>> insertListenerCache = new ConcurrentHashMap<>(); 813 814 public void invokeOnInsertListener(Object entity) { 815 List<InsertListener> listeners = MapUtil.computeIfAbsent(insertListenerCache, entityClass, aClass -> { 816 List<InsertListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 817 .getSupportedInsertListener(entityClass, CollectionUtil.isNotEmpty(onInsertListeners)); 818 List<InsertListener> allListeners = CollectionUtil.merge(onInsertListeners, globalListeners); 819 Collections.sort(allListeners); 820 return allListeners; 821 }); 822 listeners.forEach(insertListener -> insertListener.onInsert(entity)); 823 } 824 825 826 private static Map<Class<?>, List<UpdateListener>> updateListenerCache = new ConcurrentHashMap<>(); 827 828 public void invokeOnUpdateListener(Object entity) { 829 List<UpdateListener> listeners = MapUtil.computeIfAbsent(updateListenerCache, entityClass, aClass -> { 830 List<UpdateListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 831 .getSupportedUpdateListener(entityClass, CollectionUtil.isNotEmpty(onUpdateListeners)); 832 List<UpdateListener> allListeners = CollectionUtil.merge(onUpdateListeners, globalListeners); 833 Collections.sort(allListeners); 834 return allListeners; 835 }); 836 listeners.forEach(insertListener -> insertListener.onUpdate(entity)); 837 } 838 839 840 private static Map<Class<?>, List<SetListener>> setListenerCache = new ConcurrentHashMap<>(); 841 842 public Object invokeOnSetListener(Object entity, String property, Object value) { 843 List<SetListener> listeners = MapUtil.computeIfAbsent(setListenerCache, entityClass, aClass -> { 844 List<SetListener> globalListeners = FlexGlobalConfig.getDefaultConfig() 845 .getSupportedSetListener(entityClass, CollectionUtil.isNotEmpty(onSetListeners)); 846 List<SetListener> allListeners = CollectionUtil.merge(onSetListeners, globalListeners); 847 Collections.sort(allListeners); 848 return allListeners; 849 }); 850 for (SetListener setListener : listeners) { 851 value = setListener.onSet(entity, property, value); 852 } 853 return value; 854 } 855}