Solve Mybatis-Generator single instance different databases with the same table name to generate code reading error

accident scene

In my project development, due to the multi-branching of project business requirements, the data structure of each branch is evolved from the initial business. A single instance of MySQL is deployed in the development environment, and each branch adopts database isolation, but the data table name is still the same, and the difference is reflected in the data column. After I add the A field in the A database A table of the A branch, I will generate the code of the B database B table of the B branch. At this point the problem arises, the generated code contains the A field of the A table, but this is not what I want.

Troubleshooting

mybatis-generator-core version: 1.4.0
The essence of code generation is actually to read the data in the information_schema.columns table of the connected database, then analyze the database|belonging table|field type, and then generate code after processing . There is a problem, and there is no useful method for encyclopedia (or maybe my encyclopedia method is relatively simple), so there is only honest Debug. After Debug tracking, it is found that its acquisition is listed in org.mybatis.generator.internal.db.DatabaseIntrospector#getColumns, the code is as follows:

private Map<ActualTableName, List<IntrospectedColumn>> getColumns(TableConfiguration tc) throws SQLException {
    
    
        boolean delimitIdentifiers = tc.isDelimitIdentifiers() || StringUtility.stringContainsSpace(tc.getCatalog()) || StringUtility.stringContainsSpace(tc.getSchema()) || StringUtility.stringContainsSpace(tc.getTableName());
        String localCatalog;
        String localSchema;
        String localTableName;
        if (delimitIdentifiers) {
    
    
            localCatalog = tc.getCatalog();
            localSchema = tc.getSchema();
            localTableName = tc.getTableName();
        } else if (this.databaseMetaData.storesLowerCaseIdentifiers()) {
    
    
            localCatalog = tc.getCatalog() == null ? null : tc.getCatalog().toLowerCase();
            localSchema = tc.getSchema() == null ? null : tc.getSchema().toLowerCase();
            localTableName = tc.getTableName() == null ? null : tc.getTableName().toLowerCase();
        } else if (this.databaseMetaData.storesUpperCaseIdentifiers()) {
    
    
            localCatalog = tc.getCatalog() == null ? null : tc.getCatalog().toUpperCase();
            localSchema = tc.getSchema() == null ? null : tc.getSchema().toUpperCase();
            localTableName = tc.getTableName() == null ? null : tc.getTableName().toUpperCase();
        } else {
    
    
            localCatalog = tc.getCatalog();
            localSchema = tc.getSchema();
            localTableName = tc.getTableName();
        }

        if (tc.isWildcardEscapingEnabled()) {
    
    
            String escapeString = this.databaseMetaData.getSearchStringEscape();
            StringBuilder sb = new StringBuilder();
            StringTokenizer st;
            String token;
            if (localSchema != null) {
    
    
                st = new StringTokenizer(localSchema, "_%", true);

                while(true) {
    
    
                    if (!st.hasMoreTokens()) {
    
    
                        localSchema = sb.toString();
                        break;
                    }

                    token = st.nextToken();
                    if (token.equals("_") || token.equals("%")) {
    
    
                        sb.append(escapeString);
                    }

                    sb.append(token);
                }
            }

            sb.setLength(0);

            for(st = new StringTokenizer(localTableName, "_%", true); st.hasMoreTokens(); sb.append(token)) {
    
    
                token = st.nextToken();
                if (token.equals("_") || token.equals("%")) {
    
    
                    sb.append(escapeString);
                }
            }

            localTableName = sb.toString();
        }

        Map<ActualTableName, List<IntrospectedColumn>> answer = new HashMap();
        if (this.logger.isDebugEnabled()) {
    
    
            String fullTableName = StringUtility.composeFullyQualifiedTableName(localCatalog, localSchema, localTableName, '.');
            this.logger.debug(Messages.getString("Tracing.1", fullTableName));
        }
		// 这里就是Mybatis-Generator获取列的来源,由于我的项目特殊性,没有指定catalog和schema
        ResultSet rs = this.databaseMetaData.getColumns(localCatalog, localSchema, localTableName, "%");
        boolean supportsIsAutoIncrement = false;
        boolean supportsIsGeneratedColumn = false;
        ResultSetMetaData rsmd = rs.getMetaData();
        int colCount = rsmd.getColumnCount();

        for(int i = 1; i <= colCount; ++i) {
    
    
            if ("IS_AUTOINCREMENT".equals(rsmd.getColumnName(i))) {
    
    
                supportsIsAutoIncrement = true;
            }

            if ("IS_GENERATEDCOLUMN".equals(rsmd.getColumnName(i))) {
    
    
                supportsIsGeneratedColumn = true;
            }
        }

        while(rs.next()) {
    
    
            IntrospectedColumn introspectedColumn = ObjectFactory.createIntrospectedColumn(this.context);
            introspectedColumn.setTableAlias(tc.getAlias());
            introspectedColumn.setJdbcType(rs.getInt("DATA_TYPE"));
            introspectedColumn.setActualTypeName(rs.getString("TYPE_NAME"));
            introspectedColumn.setLength(rs.getInt("COLUMN_SIZE"));
            introspectedColumn.setActualColumnName(rs.getString("COLUMN_NAME"));
            introspectedColumn.setNullable(rs.getInt("NULLABLE") == 1);
            introspectedColumn.setScale(rs.getInt("DECIMAL_DIGITS"));
            introspectedColumn.setRemarks(rs.getString("REMARKS"));
            introspectedColumn.setDefaultValue(rs.getString("COLUMN_DEF"));
            if (supportsIsAutoIncrement) {
    
    
                introspectedColumn.setAutoIncrement("YES".equals(rs.getString("IS_AUTOINCREMENT")));
            }

            if (supportsIsGeneratedColumn) {
    
    
                introspectedColumn.setGeneratedColumn("YES".equals(rs.getString("IS_GENERATEDCOLUMN")));
            }

            ActualTableName atn = new ActualTableName(rs.getString("TABLE_CAT"), rs.getString("TABLE_SCHEM"), rs.getString("TABLE_NAME"));
            List<IntrospectedColumn> columns = (List)answer.get(atn);
            if (columns == null) {
    
    
                columns = new ArrayList();
                answer.put(atn, columns);
            }

            ((List)columns).add(introspectedColumn);
            if (this.logger.isDebugEnabled()) {
    
    
                this.logger.debug(Messages.getString("Tracing.2", introspectedColumn.getActualColumnName(), Integer.toString(introspectedColumn.getJdbcType()), atn.toString()));
            }
        }

        this.closeResultSet(rs);
        if (answer.size() > 1 && !StringUtility.stringContainsSQLWildcard(localSchema) && !StringUtility.stringContainsSQLWildcard(localTableName)) {
    
    
            ActualTableName inputAtn = new ActualTableName(tc.getCatalog(), tc.getSchema(), tc.getTableName());
            StringBuilder sb = new StringBuilder();
            boolean comma = false;

            ActualTableName atn;
            for(Iterator var15 = answer.keySet().iterator(); var15.hasNext(); sb.append(atn.toString())) {
    
    
                atn = (ActualTableName)var15.next();
                if (comma) {
    
    
                    sb.append(',');
                } else {
    
    
                    comma = true;
                }
            }

            this.warnings.add(Messages.getString("Warning.25", inputAtn.toString(), sb.toString()));
        }

        return answer;
    }

Among them, this.databaseMetaData.getColumns is finally called com.mysql.cj.jdbc.DatabaseMetaDataUsingInfoSchema#getColumns in the mysql driver package, which caused the definition of the read data column to be confused.

String db = this.getDatabase(catalog, schemaPattern);
db = this.pedantic ? db : StringUtils.unQuoteIdentifier(db, this.quotedId);

The com.mysql.cj.jdbc.DatabaseMetaData#getDatabase code is as follows:

protected String getDatabase(String catalog, String schema) {
    
    
        if (this.databaseTerm.getValue() == DatabaseTerm.SCHEMA) {
    
    
            return schema == null && (Boolean)this.nullDatabaseMeansCurrent.getValue() ? this.database : schema;
        } else {
    
    
            return catalog == null && (Boolean)this.nullDatabaseMeansCurrent.getValue() ? this.database : catalog;
        }
    }

Regarding the link to the original text of the official website of nullDatabaseMeansCurrent,
The original text of the official website about nullDatabaseMeansCurren
the original text roughly means: When the value of the catalog or schema parameter provided to the DatabaseMetaData method is null, does it mean that the current database is used?

solution

Add the parameter nullDatabaseMeansCurrent=true in the jdbc connection url to specify the current database

Guess you like

Origin blog.csdn.net/baidu_38956956/article/details/128629780