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