栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDBC Mysql Connection 获取不到表的Comments

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDBC Mysql Connection 获取不到表的Comments

前言

通过Connection获取当前Schema下所有表的信息,获取不到表的注释


一、怎么获取表信息

先获取JDBC的链接,调用connection.getmetaData()获取链接元数据信息,之后通过

ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException;

获取表的信息

二、出现的问题

遍历ResultSet结果,获取每个表的信息

protected ColumnDefinition createTablesFields() {
        Field[] fields = new Field[10];
        fields[0] = new Field("", "TABLE_CAT", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 255);
        fields[1] = new Field("", "TABLE_SCHEM", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[2] = new Field("", "TABLE_NAME", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 255);
        fields[3] = new Field("", "TABLE_TYPE", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 5);
        fields[4] = new Field("", "REMARKS", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[5] = new Field("", "TYPE_CAT", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[6] = new Field("", "TYPE_SCHEM", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[7] = new Field("", "TYPE_NAME", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[8] = new Field("", "SELF_REFERENCING_COL_NAME", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        fields[9] = new Field("", "REF_GENERATION", this.metadataCollationIndex, this.metadataEncoding, MysqlType.VARCHAR, 0);
        return new DefaultColumnDefinition(fields);
    }

通过ResultSet.getString(“TABLE_NAME”)获取表明,通过ResultSet.getString(“REMARKS”)获取表注释,结果表注释获取不到

三、分析 1. 分析DatabasemetaData

注意到java.sql.DatabasemetaData在mysql有两个实现:
com.mysql.cj.jdbc.DatabasemetaData和com.mysql.cj.jdbc.DatabasemetaDataUsingInfoSchema
分析两个类getTables的实现,发现DatabasemetaData执行的sql语句是SHOW FULL TABLES,DatabasemetaDataUsingInfoSchema执行的sql语句是SELECt ... FROM INFORMATION_SCHEMA.TABLES。
到这就很明显了,出现问题的时候,DatabasemetaData的实现类是DatabasemetaData,我们要改变方法,让其实现DatabasemetaDataUsingInfoSchema。

2. 分析怎么获取DatabasemetaData

追踪代码

@Override
    public java.sql.DatabasemetaData getmetaData() throws SQLException {
        return getmetaData(true, true);
    }

    private java.sql.DatabasemetaData getmetaData(boolean checkClosed, boolean checkForInfoSchema) throws SQLException {
        if (checkClosed) {
            checkClosed();
        }

        com.mysql.cj.jdbc.DatabasemetaData dbmeta = com.mysql.cj.jdbc.DatabasemetaData.getInstance(getMultiHostSafeProxy(), this.database, checkForInfoSchema,
                this.nullStatementResultSetFactory);

        if (getSession() != null && getSession().getProtocol() != null) {
            dbmeta.setmetadataEncoding(getSession().getServerSession().getCharacterSetmetadata());
            dbmeta.setmetadataCollationIndex(getSession().getServerSession().getmetadataCollationIndex());
        }

        return dbmeta;
    }

继续找DatabasemetaData.getInstance()方法

protected static DatabasemetaData getInstance(JdbcConnection connToSet, String databaseToSet, boolean checkForInfoSchema, ResultSetFactory resultSetFactory)
            throws SQLException {
        if (checkForInfoSchema && connToSet.getPropertySet().getBooleanProperty(PropertyKey.useInformationSchema).getValue()) {
            return new DatabasemetaDataUsingInfoSchema(connToSet, databaseToSet, resultSetFactory);
        }

        return new DatabasemetaData(connToSet, databaseToSet, resultSetFactory);
    }

这里就很明显了,checkForInfoSchema 一直为true,需要判断useInformationSchema的属性,当其为true的时候,实例化DatabasemetaDataUsingInfoSchema,反之就实例化DatabasemetaData。

四、解决

修改useInformationSchema为true,有两种方案

1.jdbcUrl后边追加&&useInformationSchema=true
2.Properties里面设置useInformationSchema为true

五、后续研究

在connection链接获取后续操作afterHandshake里,有下面一段代码

 // Changing defaults for 8.0.3+ server: PNAME_useInformationSchema=true
        RuntimeProperty useInformationSchema = this.propertySet.getProperty(PropertyKey.useInformationSchema);
        if (versionMeetsMinimum(8, 0, 3) && !useInformationSchema.getValue() && !useInformationSchema.isExplicitlySet()) {
            useInformationSchema.setValue(true);
        }

很明显可以看出,服务器版本在8.0.3(包含)以上的时候,代码自动添加useInformationSchema=true

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/777121.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号