All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.myoss.phoenix.mybatis.table.TableMetaObject Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018-2018 https://github.com/myoss
 *
 * 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.github.myoss.phoenix.mybatis.table;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.mapping.ResultFlag;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandler;
import org.springframework.util.ClassUtils;

import com.github.myoss.phoenix.core.exception.BizRuntimeException;
import com.github.myoss.phoenix.core.utils.NameStyle;
import com.github.myoss.phoenix.mybatis.table.annotation.Column;
import com.github.myoss.phoenix.mybatis.table.annotation.FillRule;
import com.github.myoss.phoenix.mybatis.table.annotation.GenerationType;
import com.github.myoss.phoenix.mybatis.table.annotation.SelectKey;
import com.github.myoss.phoenix.mybatis.table.annotation.SequenceGenerator;
import com.github.myoss.phoenix.mybatis.table.annotation.SequenceKey;
import com.github.myoss.phoenix.mybatis.table.annotation.Table;
import com.github.myoss.phoenix.mybatis.type.UnsupportedTypeHandler;

/**
 * 数据库表结构信息工具类
 *
 * @author Jerry.Chen
 * @since 2018年4月26日 上午10:46:25
 */
public class TableMetaObject {
    /**
     * 实体类 => 表对象
     */
    private static final Map, TableInfo>    ENTITY_TABLE_MAP     = new ConcurrentHashMap<>();
    private static final Map       SEQUENCE_BEAN_MAP    = new ConcurrentHashMap<>();
    private static final Class PERSISTENCE_ID_CLASS = resolveAnnotationClassName(
            "javax.persistence.Id");

    /**
     * 判断 Annotation Class 是否存在,如果存在,返回 Class 对象
     *
     * @param className class full name
     * @return Annotation Class
     */
    @SuppressWarnings("unchecked")
    public static Class resolveAnnotationClassName(String className) {
        ClassLoader classLoader = TableMetaObject.class.getClassLoader();
        if (ClassUtils.isPresent(className, classLoader)) {
            return (Class) ClassUtils.resolveClassName(className, classLoader);
        }
        return null;
    }

    /**
     * 将"序列生成器实例对象"添加到缓存中
     *
     * @param sequenceBeanName 序列的 Spring Bean 实例名称
     * @param sequence 序列生成器实例对象
     */
    public static void addSequenceBean(String sequenceBeanName, Sequence sequence) {
        if (SEQUENCE_BEAN_MAP.containsKey(sequenceBeanName)) {
            throw new IllegalArgumentException(
                    "already contains value for " + sequenceBeanName + ", sequence: " + sequence);
        }
        SEQUENCE_BEAN_MAP.putIfAbsent(sequenceBeanName, sequence);
    }

    /**
     * 获取缓存中的"序列生成器实例对象"
     *
     * @param sequenceBeanName 序列的 Spring Bean 实例名称
     * @return 序列生成器实例对象
     */
    public static Sequence getSequenceBean(String sequenceBeanName) {
        return SEQUENCE_BEAN_MAP.get(sequenceBeanName);
    }

    /**
     * 获取缓存中的全部"序列生成器实例对象"
     *
     * @return 全部"序列生成器实例对象"
     */
    public static Map getSequenceBeanMap() {
        return SEQUENCE_BEAN_MAP;
    }

    /**
     * 获取缓存中的全部"数据库表结构信息"
     *
     * @return 全部"数据库表结构信息"
     */
    public static Map, TableInfo> getTableInfoMap() {
        return ENTITY_TABLE_MAP;
    }

    /**
     * 获取缓存中的"数据库表结构信息"
     *
     * @param entityClass 实体类class
     * @return 数据库表结构信息
     */
    public static TableInfo getTableInfo(Class entityClass) {
        return ENTITY_TABLE_MAP.get(entityClass);
    }

    /**
     * 根据"mapper interface class" 中的泛型获取"实体类class"
     *
     * @param mapperInterfaceClass mapper interface class
     * @return 实体类class
     */
    public static Class getEntityClassByMapperInterface(Class mapperInterfaceClass) {
        Type[] types = mapperInterfaceClass.getGenericInterfaces();
        for (Type type : types) {
            if (type instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
                if (actualTypeArguments.length == 0) {
                    continue;
                }
                return (Class) actualTypeArguments[0];
            }
        }
        return null;
    }

    /**
     * 获取缓存中的"数据库表结构信息",或者获取初始化"数据库表结构信息"
     *
     * @param mapperInterface mapper interface class
     * @param config MyBatis Table 全局配置;实体类映射数据库表的全局配置
     * @param configuration MyBatis 全局配置
     * @return 数据库表结构信息
     */
    public static TableInfo getTableInfoByMapperInterface(Class mapperInterface, TableConfig config,
                                                          Configuration configuration) {
        Class entityClass = getEntityClassByMapperInterface(mapperInterface);
        TableInfo tableInfo = getTableInfo(entityClass, config, configuration);
        tableInfo.setMapperInterfaceClass(mapperInterface);
        return tableInfo;
    }

    /**
     * 获取缓存中的"数据库表结构信息",或者获取初始化"数据库表结构信息"
     *
     * @param entityClass 实体类class
     * @param config MyBatis Table 全局配置;实体类映射数据库表的全局配置
     * @param configuration MyBatis 全局配置
     * @return 数据库表结构信息
     */
    public static TableInfo getTableInfo(Class entityClass, TableConfig config, Configuration configuration) {
        TableInfo tableInfo = ENTITY_TABLE_MAP.get(entityClass);
        if (tableInfo != null) {
            return tableInfo;
        }
        NameStyle tableNameStyle = config.getTableNameStyle();
        tableInfo = new TableInfo();
        tableInfo.setCatalog(config.getCatalog());
        tableInfo.setSchema(config.getSchema());
        if (entityClass.isAnnotationPresent(Table.class)) {
            Table table = entityClass.getAnnotation(Table.class);
            String catalog = StringUtils.defaultIfBlank(table.catalog(), config.getCatalog());
            String schema = StringUtils.defaultIfBlank(table.schema(), config.getSchema());
            tableInfo.setCatalog(catalog);
            tableInfo.setSchema(schema);
            if (StringUtils.isNotBlank(table.name())) {
                String name = config.getTableNamePrefix() + table.name() + config.getTableNameSuffix();
                tableInfo.setTableName(name);
            }
            if (StringUtils.isNotBlank(table.escapedName())) {
                String name = config.getTableNamePrefix() + table.escapedName() + config.getTableNameSuffix();
                tableInfo.setEscapedTableName(name);
            }
            tableNameStyle = table.nameStyle();
        }
        if (StringUtils.isBlank(tableInfo.getTableName())) {
            String name = tableNameStyle.transform(entityClass.getSimpleName());
            String tableName = config.getTableNamePrefix() + name + config.getTableNameSuffix();
            tableInfo.setTableName(tableName);
        }
        tableInfo.setEntityClass(entityClass);
        initTableSequence(entityClass.getAnnotation(SequenceGenerator.class), tableInfo, null);
        TableSequence tableSequence = tableInfo.getTableSequence();
        String[] keyProperties = (tableSequence != null ? tableSequence.getKeyProperties() : null);
        String[] keyColumns = new String[(keyProperties != null ? keyProperties.length : 0)];
        Class[] resultTypes = new Class[(keyProperties != null ? keyProperties.length : 0)];

        // 处理字段信息
        NameStyle columnNameStyle = config.getColumnNameStyle();
        Set columns = new LinkedHashSet<>();
        Set pkColumns = new LinkedHashSet<>();
        Set logicDeleteColumns = new LinkedHashSet<>();
        Map propertyDescriptorMap = getPropertyDescriptorMap(entityClass);
        List fields = getFieldList(entityClass);
        for (Field field : fields) {
            String name = field.getName();
            TableColumnInfo columnInfo = new TableColumnInfo();
            columnInfo.setTableInfo(tableInfo);
            columnInfo.setProperty(name);
            PropertyDescriptor propertyDescriptor = propertyDescriptorMap.get(name);
            columnInfo.setJavaType(propertyDescriptor.getPropertyType());
            columnInfo.setPropertyDescriptor(propertyDescriptor);
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                if (column.isTransient()) {
                    // 忽略非数据库字段
                    continue;
                }
                if (StringUtils.isNotBlank(column.name())) {
                    columnInfo.setColumn(column.name());
                }
                if (StringUtils.isNotBlank(column.escapedName())) {
                    columnInfo.setEscapedColumn(column.escapedName());
                }
                if (column.primaryKey()) {
                    columnInfo.setPrimaryKey(true);
                }
                if (column.typeHandler() != UnsupportedTypeHandler.class) {
                    columnInfo.setTypeHandler(column.typeHandler());
                }
                columnInfo.setInsertable(column.insertable());
                columnInfo.setUpdatable(column.updatable());
                columnInfo.setSelectable(column.selectable());
                Map fillRules = Stream.of(column.fillRule())
                        .filter(s -> !FillRule.NONE.equals(s))
                        .collect(Collectors.toMap(Function.identity(), FillRule::getValue));
                columnInfo.setFillRules(fillRules);
            }
            if (StringUtils.isBlank(columnInfo.getColumn())) {
                columnInfo.setColumn(columnNameStyle.transform(name));
            }
            initLogicDelete(config, tableInfo, columnInfo, column, logicDeleteColumns);

            if (!columnInfo.isPrimaryKey() && PERSISTENCE_ID_CLASS != null
                    && field.isAnnotationPresent(PERSISTENCE_ID_CLASS)) {
                columnInfo.setPrimaryKey(true);
            }
            if (columnInfo.isPrimaryKey()) {
                pkColumns.add(columnInfo);
            }

            // 收集序列字段信息
            int indexOf = ArrayUtils.indexOf(keyProperties, columnInfo.getProperty());
            if (indexOf > -1) {
                // 收集数据库字段名
                keyColumns[indexOf] = columnInfo.getColumn();
                resultTypes[indexOf] = columnInfo.getJavaType();
            }
            initTableSequence(field.getAnnotation(SequenceGenerator.class), tableInfo, columnInfo);
            columns.add(columnInfo);
        }
        tableInfo.setColumns(columns);
        tableInfo.setPrimaryKeyColumns(pkColumns);
        tableInfo.setLogicDeleteColumns(logicDeleteColumns);
        if (keyProperties != null && keyColumns.length > 0
                && ArrayUtils.isEmpty(tableInfo.getTableSequence().getKeyColumns())) {
            // 如果 @SequenceGenerator 注解放在 class 上,并且没有设置 keyColumns 属性,则取相应 keyProperty 中的字段名
            tableInfo.getTableSequence().setKeyColumns(keyColumns);
        }
        if (keyProperties != null && resultTypes.length > 0
                && ArrayUtils.isEmpty(tableInfo.getTableSequence().getResultType())) {
            // 如果 @SequenceGenerator 注解放在 class 上,并且没有设置 resultType 属性,则取相应 keyProperty 中的字段类型
            tableInfo.getTableSequence().setResultType(resultTypes);
        }

        // 生成实体的 BaseResultMap 对象
        tableInfo.setBaseResultMap(builderBaseResultMap(tableInfo, configuration));
        // 生成 select 查询所有列sql语句
        tableInfo.setSelectAllColumnsSql(builderSelectAllColumns(tableInfo));
        // 生成 where 主键条件sql语句
        tableInfo.setWherePrimaryKeySql(builderWherePrimaryKeySql(tableInfo, false));
        tableInfo.setWherePrimaryKeyIncludeLogicDeleteSql(builderWherePrimaryKeySql(tableInfo, true));
        // 生成 where 所有条件sql语句
        tableInfo.setWhereConditionSql(builderWhereConditionSql(tableInfo, false));
        tableInfo.setWhereConditionIncludeLogicDeleteSql(builderWhereConditionSql(tableInfo, true));
        // 生成 where 所有条件sql语句,带有参数前缀
        tableInfo.setWhereConditionWithParameterSql(
                builderWhereConditionWithParameterSql(tableInfo, false, "condition"));
        tableInfo.setWhereConditionWithParameterIncludeLogicDeleteSql(
                builderWhereConditionWithParameterSql(tableInfo, true, "condition"));
        tableInfo.setTableConfig(config);
        tableInfo.setConfiguration(configuration);
        ENTITY_TABLE_MAP.put(entityClass, tableInfo);
        return tableInfo;
    }

    /**
     * 加载数据库表"序列生成器"属性配置
     *
     * @param sequenceGenerator 序列生成器规则
     * @param tableInfo 数据库表结构信息
     * @param columnInfo 数据库表结构字段信息
     */
    private static void initTableSequence(SequenceGenerator sequenceGenerator, TableInfo tableInfo,
                                          TableColumnInfo columnInfo) {
        if (sequenceGenerator == null) {
            return;
        }
        if (tableInfo.getTableSequence() != null) {
            // 自增序列只能有一个
            throw new BindingException(
                    "more than one sequence field: [" + tableInfo.getTableSequence() + ", " + columnInfo + "]");
        }

        GenerationType strategy = sequenceGenerator.strategy();
        TableSequence tableSequence = new TableSequence();
        if (strategy == GenerationType.USE_GENERATED_KEYS) {
            if (columnInfo != null) {
                columnInfo.setAutoIncrement(true);
            }
        } else if (strategy == GenerationType.SELECT_KEY) {
            SelectKey selectKey = sequenceGenerator.selectKey();
            tableSequence.setKeyProperties(selectKey.keyProperty());
            tableSequence.setKeyColumns(selectKey.keyColumn());
            if (selectKey.resultType() != Class.class) {
                tableSequence.setResultType(new Class[] { selectKey.resultType() });
            }
            tableSequence.setSql(selectKey.sql());
            tableSequence.setStatementType(selectKey.statementType());
            tableSequence.setOrder(selectKey.order());
            if (columnInfo != null) {
                if (ArrayUtils.isEmpty(tableSequence.getKeyProperties())) {
                    tableSequence.setKeyProperties(new String[] { columnInfo.getProperty() });
                }
                if (ArrayUtils.isEmpty(tableSequence.getKeyColumns())) {
                    tableSequence.setKeyColumns(new String[] { columnInfo.getColumn() });
                }
                if (ArrayUtils.isEmpty(tableSequence.getResultType())) {
                    tableSequence.setResultType(new Class[] { columnInfo.getJavaType() });
                }
            }
        } else if (strategy == GenerationType.SEQUENCE_KEY) {
            SequenceKey sequenceKey = sequenceGenerator.sequenceKey();
            tableSequence.setKeyProperties(sequenceKey.keyProperty());
            tableSequence.setKeyColumns(sequenceKey.keyColumn());
            tableSequence.setSequenceClass(sequenceKey.sequenceClass());
            tableSequence.setSequenceBeanName(sequenceKey.sequenceBeanName());
            tableSequence.setSequenceName(sequenceKey.sequenceName());
            tableSequence.setOrder(sequenceKey.order());
            if (columnInfo != null) {
                if (ArrayUtils.isEmpty(tableSequence.getKeyProperties())) {
                    tableSequence.setKeyProperties(new String[] { columnInfo.getProperty() });
                }
                if (ArrayUtils.isEmpty(tableSequence.getKeyColumns())) {
                    tableSequence.setKeyColumns(new String[] { columnInfo.getColumn() });
                }
            }
        } else {
            throw new UnsupportedOperationException("keyGenerator strategy " + strategy.getType() + " unsupported");
        }

        if (strategy != GenerationType.USE_GENERATED_KEYS && ArrayUtils.isEmpty(tableSequence.getKeyProperties())) {
            throw new BindingException("keyProperty value is blank: " + sequenceGenerator);
        }
        tableSequence.setStrategy(strategy);
        tableInfo.setTableSequence(tableSequence);
    }

    /**
     * 初始化"逻辑删除"字段
     *
     * @param config MyBatis Table 全局配置
     * @param tableInfo 数据库表结构信息
     * @param columnInfo 数据库表结构字段信息
     * @param column 数据库字段的注解信息
     * @param logicDeleteColumns 逻辑删除字段信息
     */
    private static void initLogicDelete(TableConfig config, TableInfo tableInfo, TableColumnInfo columnInfo,
                                        Column column, Set logicDeleteColumns) {
        boolean isLogicDelete = false;
        String deleteValue = null;
        String unDeleteValue = null;
        if (column != null && column.logicDelete()) {
            isLogicDelete = true;
            unDeleteValue = StringUtils.defaultIfBlank(column.logicUnDeleteValue(), config.getLogicUnDeleteValue());
            deleteValue = StringUtils.defaultIfBlank(column.logicDeleteValue(), config.getLogicDeleteValue());
        } else if (config.isLogicDelete() && columnInfo.getColumn().equals(config.getLogicDeleteColumnName())) {
            isLogicDelete = true;
            deleteValue = config.getLogicDeleteValue();
            unDeleteValue = config.getLogicUnDeleteValue();
        }
        if (isLogicDelete) {
            if (StringUtils.isAnyBlank(deleteValue, unDeleteValue)) {
                throw new BindingException("logicDeleteValue or logicUnDeleteValue is blank, [logicDeleteValue="
                        + deleteValue + ", logicUnDeleteValue=" + unDeleteValue + "]");
            }
            columnInfo.setLogicDelete(true);
            columnInfo.setLogicDeleteValue(deleteValue);
            columnInfo.setLogicUnDeleteValue(unDeleteValue);
            tableInfo.setLogicDelete(true);
            logicDeleteColumns.add(columnInfo);
        }
    }

    /**
     * 获取 {@code clazz } Class 中的所有字段,排除 static, transient
     * 字段,包含父类中的字段(重写的字段只会保留一个)
     *
     * @param clazz 反射类
     * @return 所有字段信息
     */
    public static List getFieldList(Class clazz) {
        Class currentClass = Objects.requireNonNull(clazz);
        List allFields = new ArrayList<>();
        Map allFiledName = new HashMap<>();
        boolean isSupper = false;
        while (currentClass != null) {
            Field[] declaredFields = currentClass.getDeclaredFields();
            int idx = 0;
            for (Field field : declaredFields) {
                String name = field.getName();
                if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers())) {
                    // 过滤字段: static, transient
                    continue;
                }
                if (isSupper && allFiledName.containsKey(name)) {
                    // 过滤子类已经重写的字段
                    continue;
                }
                allFiledName.put(name, true);
                if (isSupper) {
                    allFields.add(idx++, field);
                } else {
                    allFields.add(field);
                }
            }
            isSupper = true;
            currentClass = currentClass.getSuperclass();
        }
        return allFields;
    }

    /**
     * 获取 {@code clazz } Class 中所有的 getter/setter 方法
     *
     * @param clazz 反射类
     * @return clazz 所有的 getter/setter 方法
     */
    public static Map getPropertyDescriptorMap(Class clazz) {
        BeanInfo beanInfo;
        try {
            beanInfo = Introspector.getBeanInfo(clazz);
        } catch (IntrospectionException e) {
            throw new BizRuntimeException(e);
        }
        PropertyDescriptor[] descriptors = beanInfo.getPropertyDescriptors();
        return Stream.of(descriptors).filter(s -> !"class".equals(s.getName())).collect(
                Collectors.toMap(PropertyDescriptor::getName, Function.identity()));
    }

    /**
     * 获取数据库完整的表名
     *
     * @param tableInfo 数据库表结构信息
     * @return catalog.schema.tableName
     */
    public static String getTableName(TableInfo tableInfo) {
        return Stream.of(tableInfo.getCatalog(), tableInfo.getSchema(), tableInfo.getActualTableName())
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.joining("."));
    }

    /**
     * 生成实体的 BaseResultMap 对象,表映射结果集。类似 Mapper XML 中效果:
     *
     * 
     * <resultMap id="BaseResultMap" type="entityClass package">
     *   <id column="id" jdbcType="BIGINT" property="id" />
     * </resultMap>
     * 
* * @param tableInfo 数据库表结构信息 * @param configuration Mybatis configuration * @return BaseResultMap 对象 */ public static ResultMap builderBaseResultMap(TableInfo tableInfo, Configuration configuration) { List resultMappings = new ArrayList<>(); for (TableColumnInfo item : tableInfo.getColumns()) { ResultMapping.Builder builder = new ResultMapping.Builder(configuration, item.getProperty(), item.getColumn(), item.getJavaType()); if (item.getJdbcType() != null) { builder.jdbcType(item.getJdbcType()); } if (item.getTypeHandler() != null) { try { TypeHandler typeHandler = item.getTypeHandler().newInstance(); builder.typeHandler(typeHandler); } catch (InstantiationException | IllegalAccessException e) { throw new BizRuntimeException(e); } } List flags = new ArrayList<>(); if (item.isPrimaryKey()) { flags.add(ResultFlag.ID); } builder.flags(flags); resultMappings.add(builder.build()); } ResultMap.Builder builder = new ResultMap.Builder(configuration, "BaseResultMap", tableInfo.getEntityClass(), resultMappings, true); return builder.build(); } /** * 生成 select 查询所有列sql语句,示例如下: * *
     * id, name, code
     * 
* * @param tableInfo 数据库表结构信息 * @return sql语句 */ public static String builderSelectAllColumns(TableInfo tableInfo) { return tableInfo.getColumns() .stream() .filter(TableColumnInfo::isSelectable) .map(TableColumnInfo::getActualColumn) .collect(Collectors.joining(", ")); } /** * 生成 where 所有条件sql语句({@code includeLogicDelete = false} * ,如果表是逻辑删除,会添加逻辑删除的字段),示例如下: * *
     * <where>
     *  <if test="id != null">
     *    and id = #{id}
     *  </if>
     *  AND is_deleted = 'N'
     * </where>
     * 
* * @param tableInfo 数据库表结构信息 * @param includeLogicDelete 是否不过滤掉已经被标记为逻辑删除({@link Column#logicDelete})的数据 * @return sql语句 */ public static StringBuilder builderWhereConditionSql(TableInfo tableInfo, boolean includeLogicDelete) { StringBuilder sql = new StringBuilder(1024); sql.append("\n"); for (TableColumnInfo item : tableInfo.getColumns()) { if (!includeLogicDelete && item.isLogicDelete()) { continue; } sql.append(" \n"); sql.append(" and ").append(item.getActualColumn()).append(" = #{").append(item.getProperty()); if (item.getJdbcType() != null) { sql.append(",jdbcType=").append(item.getJdbcType().name()); } sql.append("}\n"); sql.append(" \n"); } if (!includeLogicDelete && tableInfo.isLogicDelete()) { for (TableColumnInfo item : tableInfo.getLogicDeleteColumns()) { sql.append(" and ").append(item.getActualColumn()).append(" = "); if (CharSequence.class.isAssignableFrom(item.getJavaType())) { sql.append("'").append(item.getLogicUnDeleteValue()).append("'"); } else { sql.append(item.getLogicUnDeleteValue()); } sql.append("\n"); } } sql.append(""); return sql; } /** * 生成 where 所有条件sql语句({@code includeLogicDelete = false} * ,如果表是逻辑删除,会添加逻辑删除的字段),带有参数前缀,示例如下: * *
     * <where>
     *  <if test="conditionPrefix.id != null">
     *    and id = #{conditionPrefix.id}
     *  </if>
     *  AND is_deleted = 'N'
     * </where>
     * 
* * @param tableInfo 数据库表结构信息 * @param includeLogicDelete 是否不过滤掉已经被标记为逻辑删除({@link Column#logicDelete})的数据 * @param conditionPrefix 参数前缀 * @return sql语句 */ public static StringBuilder builderWhereConditionWithParameterSql(TableInfo tableInfo, boolean includeLogicDelete, String conditionPrefix) { String prefix = conditionPrefix + "."; StringBuilder sql = new StringBuilder(2048); sql.append("\n"); sql.append(" \n"); for (TableColumnInfo item : tableInfo.getColumns()) { if (!includeLogicDelete && item.isLogicDelete()) { continue; } sql.append(" \n"); sql.append(" and ").append(item.getActualColumn()).append(" = #{").append(prefix).append( item.getProperty()); if (item.getJdbcType() != null) { sql.append(",jdbcType=").append(item.getJdbcType().name()); } sql.append("}\n"); sql.append(" \n"); } sql.append(" \n"); if (!includeLogicDelete && tableInfo.isLogicDelete()) { for (TableColumnInfo item : tableInfo.getLogicDeleteColumns()) { sql.append(" and ").append(item.getActualColumn()).append(" = "); if (CharSequence.class.isAssignableFrom(item.getJavaType())) { sql.append("'").append(item.getLogicUnDeleteValue()).append("'"); } else { sql.append(item.getLogicUnDeleteValue()); } sql.append("\n"); } } sql.append(""); return sql; } /** * 生成 where 主键条件sql语句({@code includeLogicDelete = false} * ,如果表是逻辑删除,会添加逻辑删除的字段),示例如下: * *
     * <where>
     *  AND id = #{id}
     *  AND is_deleted = 'N'
     * </where>
     * 
* * @param tableInfo 数据库表结构信息 * @param includeLogicDelete 是否不过滤掉已经被标记为逻辑删除({@link Column#logicDelete})的数据 * @return sql语句 */ public static StringBuilder builderWherePrimaryKeySql(TableInfo tableInfo, boolean includeLogicDelete) { StringBuilder sql = new StringBuilder(128); sql.append("\n"); for (TableColumnInfo columnInfo : tableInfo.getPrimaryKeyColumns()) { sql.append(" AND ").append(columnInfo.getActualColumn()).append(" = "); sql.append("#{").append(columnInfo.getProperty()); if (columnInfo.getJdbcType() != null) { sql.append(",jdbcType=BIGINT"); } sql.append("}\n"); } if (!includeLogicDelete && tableInfo.isLogicDelete()) { for (TableColumnInfo item : tableInfo.getLogicDeleteColumns()) { sql.append(" AND ").append(item.getActualColumn()).append(" = "); if (CharSequence.class.isAssignableFrom(item.getJavaType())) { sql.append("'").append(item.getLogicUnDeleteValue()).append("'"); } else { sql.append(item.getLogicUnDeleteValue()); } sql.append("\n"); } } sql.append(""); return sql; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy