Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.mybatisflex.core.table;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.InsertListener;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.SetListener;
import com.mybatisflex.annotation.UpdateListener;
import com.mybatisflex.core.FlexConsts;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.constant.SqlConsts;
import com.mybatisflex.core.constant.SqlOperator;
import com.mybatisflex.core.dialect.IDialect;
import com.mybatisflex.core.dialect.OperateType;
import com.mybatisflex.core.exception.FlexExceptions;
import com.mybatisflex.core.exception.locale.LocalizedFormats;
import com.mybatisflex.core.logicdelete.LogicDeleteManager;
import com.mybatisflex.core.mybatis.TypeHandlerObject;
import com.mybatisflex.core.optimisticlock.OptimisticLockManager;
import com.mybatisflex.core.query.Brackets;
import com.mybatisflex.core.query.CPI;
import com.mybatisflex.core.query.Join;
import com.mybatisflex.core.query.QueryColumn;
import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryTable;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.query.SelectQueryColumn;
import com.mybatisflex.core.query.SelectQueryTable;
import com.mybatisflex.core.query.SqlOperators;
import com.mybatisflex.core.query.UnionWrapper;
import com.mybatisflex.core.row.Row;
import com.mybatisflex.core.tenant.TenantManager;
import com.mybatisflex.core.update.RawValue;
import com.mybatisflex.core.update.UpdateWrapper;
import com.mybatisflex.core.util.ArrayUtil;
import com.mybatisflex.core.util.ClassUtil;
import com.mybatisflex.core.util.CollectionUtil;
import com.mybatisflex.core.util.ConvertUtil;
import com.mybatisflex.core.util.EnumWrapper;
import com.mybatisflex.core.util.FieldWrapper;
import com.mybatisflex.core.util.MapUtil;
import com.mybatisflex.core.util.ObjectUtil;
import com.mybatisflex.core.util.SqlUtil;
import com.mybatisflex.core.util.StringUtil;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.Reflector;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.mybatisflex.core.constant.SqlConsts.AND;
import static com.mybatisflex.core.constant.SqlConsts.EQUALS_PLACEHOLDER;
import static com.mybatisflex.core.constant.SqlConsts.IN;
public class TableInfo {
// column 和 java 属性的称的关系映射
private final Map columnInfoMapping = new HashMap<>();
// property:column
private final Map propertyColumnMapping = new LinkedHashMap<>();
private String schema; // schema
private boolean camelToUnderline = true;
private String dataSource;
private String comment;
private String tableName; // 表名
private Class> entityClass; // 实体类
// 逻辑删除数据库列名
private String logicDeleteColumn;
// 乐观锁字段
private String versionColumn;
// 租户ID 字段
private String tenantIdColumn;
// 数据插入时,默认插入数据字段
private Map onInsertColumns;
private String[] allColumns = new String[0];
// 数据更新时,默认更新内容的字段
private Map onUpdateColumns;
// 大字段列
private String[] largeColumns = new String[0];
// 默认查询列,排除 large 等字段
private String[] defaultQueryColumns = new String[0];
// 所有的字段,但除了主键的列
private String[] columns = new String[0];
private List columnInfoList;
private List primaryKeyList;
// 主键字段
private String[] primaryColumns = new String[0];
private final Map columnQueryMapping = new HashMap<>();
// 在插入数据的时候,支持主动插入的主键字段,自增字段不需要主动插入
// 但通过自定义生成器生成 或者 Sequence 在 before 生成的时候,是需要主动插入数据的
private String[] insertPrimaryKeys;
private List onInsertListeners;
private List onUpdateListeners;
private List onSetListeners;
/**
* 对应 MapperXML 配置文件中 {@code } 标签下的 {@code } 标签。
*/
private Map> associationType;
/**
* 对应 MapperXML 配置文件中 {@code } 标签下的 {@code } 标签。
*/
private Map> collectionType;
private final ReflectorFactory reflectorFactory = new BaseReflectorFactory() {
@Override
public Reflector findForClass(Class> type) {
return getReflector();
}
};
private Reflector reflector; // 反射工具
public String getSchema() {
return schema;
}
public void setSchema(String schema) {
this.schema = schema;
}
public Map getPropertyColumnMapping() {
return this.propertyColumnMapping;
}
public String getTableName() {
return tableName;
}
public String getTableNameWithSchema() {
return StringUtil.buildSchemaWithTable(schema, tableName);
}
public String getWrapSchemaAndTableName(IDialect dialect, OperateType operateType) {
if (StringUtil.hasText(schema)) {
String table = dialect.getRealTable(tableName, operateType);
return dialect.wrap(dialect.getRealSchema(schema, table, operateType)) + "." + dialect.wrap(table);
} else {
return dialect.wrap(dialect.getRealTable(tableName, operateType));
}
}
public void setTableName(String tableName) {
int indexOf = tableName.indexOf(".");
if (indexOf > 0) {
if (StringUtil.noText(schema)) {
this.schema = tableName.substring(0, indexOf);
this.tableName = tableName.substring(indexOf + 1);
} else {
this.tableName = tableName;
}
} else {
this.tableName = tableName;
}
}
public Class> getEntityClass() {
return entityClass;
}
public void setEntityClass(Class> entityClass) {
this.entityClass = entityClass;
}
public boolean isCamelToUnderline() {
return camelToUnderline;
}
public void setCamelToUnderline(boolean camelToUnderline) {
this.camelToUnderline = camelToUnderline;
}
public String getDataSource() {
return dataSource;
}
public void setDataSource(String dataSource) {
this.dataSource = dataSource;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public String getLogicDeleteColumnOrSkip() {
return LogicDeleteManager.getLogicDeleteColumn(logicDeleteColumn);
}
public String getLogicDeleteColumn() {
return logicDeleteColumn;
}
public void setLogicDeleteColumn(String logicDeleteColumn) {
this.logicDeleteColumn = logicDeleteColumn;
}
public String getOptimisticLockColumnOrSkip() {
return OptimisticLockManager.getOptimisticLockColumn(versionColumn);
}
public String getVersionColumn() {
return versionColumn;
}
public void setVersionColumn(String versionColumn) {
this.versionColumn = versionColumn;
}
public String getTenantIdColumn() {
return tenantIdColumn;
}
public void setTenantIdColumn(String tenantIdColumn) {
this.tenantIdColumn = tenantIdColumn;
}
public Map getOnInsertColumns() {
return onInsertColumns;
}
public void setOnInsertColumns(Map onInsertColumns) {
this.onInsertColumns = onInsertColumns;
}
public Map getOnUpdateColumns() {
return onUpdateColumns;
}
public void setOnUpdateColumns(Map onUpdateColumns) {
this.onUpdateColumns = onUpdateColumns;
}
public String[] getLargeColumns() {
return largeColumns;
}
public void setLargeColumns(String[] largeColumns) {
this.largeColumns = largeColumns;
}
public String[] getDefaultQueryColumns() {
return defaultQueryColumns;
}
public void setDefaultQueryColumns(String[] defaultQueryColumns) {
this.defaultQueryColumns = defaultQueryColumns;
}
public String[] getInsertPrimaryKeys() {
return insertPrimaryKeys;
}
public void setInsertPrimaryKeys(String[] insertPrimaryKeys) {
this.insertPrimaryKeys = insertPrimaryKeys;
}
public Reflector getReflector() {
return reflector;
}
public ReflectorFactory getReflectorFactory() {
return reflectorFactory;
}
public void setReflector(Reflector reflector) {
this.reflector = reflector;
}
public String[] getAllColumns() {
return allColumns;
}
public void setAllColumns(String[] allColumns) {
this.allColumns = allColumns;
}
public String[] getColumns() {
return columns;
}
public void setColumns(String[] columns) {
this.columns = columns;
}
public String[] getPrimaryColumns() {
return primaryColumns;
}
public void setPrimaryColumns(String[] primaryColumns) {
this.primaryColumns = primaryColumns;
}
public List getOnInsertListeners() {
return onInsertListeners;
}
public void setOnInsertListeners(List onInsertListeners) {
this.onInsertListeners = onInsertListeners;
}
public List getOnUpdateListeners() {
return onUpdateListeners;
}
public void setOnUpdateListeners(List onUpdateListeners) {
this.onUpdateListeners = onUpdateListeners;
}
public List getOnSetListeners() {
return onSetListeners;
}
public void setOnSetListeners(List onSetListeners) {
this.onSetListeners = onSetListeners;
}
public List getColumnInfoList() {
return columnInfoList;
}
public String getColumnByProperty(String property) {
String column = propertyColumnMapping.get(property);
// 用于兼容字段MM不规范的情况
// fix https://gitee.com/mybatis-flex/mybatis-flex/issues/I9PDYO
if (column == null) {
for (Map.Entry entry : propertyColumnMapping.entrySet()) {
if (property.equalsIgnoreCase(entry.getKey())) {
column = entry.getValue();
break;
}
}
}
return StringUtil.hasText(column) ? column : property;
}
public Map> getAssociationType() {
return associationType;
}
public void setAssociationType(Map> associationType) {
this.associationType = associationType;
}
public void addAssociationType(String fieldName, Class> clazz) {
if (associationType == null) {
associationType = new HashMap<>();
}
associationType.put(fieldName, clazz);
}
public Map> getCollectionType() {
return collectionType;
}
public void setCollectionType(Map> collectionType) {
this.collectionType = collectionType;
}
public void addCollectionType(Field field, Class> genericClass) {
if (collectionType == null) {
collectionType = new HashMap<>();
}
collectionType.put(field, genericClass);
}
void setColumnInfoList(List columnInfoList) {
this.columnInfoList = columnInfoList;
List columnNames = new ArrayList<>();
for (int i = 0; i < columnInfoList.size(); i++) {
ColumnInfo columnInfo = columnInfoList.get(i);
// 真正的字段(没有做忽略标识)
if (!columnInfo.isIgnore()) {
columnNames.add(columnInfo.column);
columnInfoMapping.put(columnInfo.column, columnInfo);
propertyColumnMapping.put(columnInfo.property, columnInfo.column);
String[] alias = columnInfo.getAlias();
columnQueryMapping.put(columnInfo.column, new QueryColumn(schema, tableName, columnInfo.column, alias != null && alias.length > 0 ? alias[0] : null));
}
}
this.columns = columnNames.toArray(new String[]{});
this.allColumns = ArrayUtil.concat(allColumns, columns);
}
public List getPrimaryKeyList() {
return primaryKeyList;
}
void setPrimaryKeyList(List primaryKeyList) {
this.primaryKeyList = primaryKeyList;
this.primaryColumns = new String[primaryKeyList.size()];
List insertIdFields = new ArrayList<>();
for (int i = 0; i < primaryKeyList.size(); i++) {
IdInfo idInfo = primaryKeyList.get(i);
primaryColumns[i] = idInfo.getColumn();
if (idInfo.getKeyType() != KeyType.Auto
&& (idInfo.getBefore() != null && idInfo.getBefore())
) {
insertIdFields.add(idInfo.getColumn());
}
columnInfoMapping.put(idInfo.column, idInfo);
propertyColumnMapping.put(idInfo.property, idInfo.column);
String[] alias = idInfo.getAlias();
columnQueryMapping.put(idInfo.column, new QueryColumn(schema, tableName, idInfo.column, alias != null && alias.length > 0 ? alias[0] : null));
}
this.allColumns = ArrayUtil.concat(allColumns, primaryColumns);
this.insertPrimaryKeys = insertIdFields.toArray(new String[0]);
}
/**
* 构建 insert 的 Sql 参数
*
* @param entity 从 entity 中获取
* @param ignoreNulls 是否忽略 null 值
* @return 数组
*/
public Object[] buildInsertSqlArgs(Object entity, boolean ignoreNulls) {
MetaObject metaObject = EntityMetaObject.forObject(entity, reflectorFactory);
String[] insertColumns = obtainInsertColumns(entity, ignoreNulls);
Map rawValueMap = obtainUpdateRawValueMap(entity);
List