码迷,mamicode.com
首页 > 数据库 > 详细

DatabaseMetadata.getTables()方法 问题记录

时间:2019-07-05 16:44:07      阅读:729      评论:0      收藏:0      [点我收藏+]

标签:str   删掉   turn   同步   types   数据   出错   检索   system   

之前写了一个程序,负责从一个集群中同步Hive数据到另一个集群中,代码中有这么一步,指定好表格后,会首先判断表格是否存在,不存在则创建,已经存在则提示是否覆盖。

在我最初编写程序的时候,两个集群中的表格基本上都是一致的,所以当初没有出什么问题。但是最近组长说这个程序干脆整合到平台里好了,所以找了一个前辈来帮我测试。

前辈不愧是前辈,噼里啪啦没多久就找出一堆小问题(主要因为最初是给自己写的,没有考虑那么多),其中一个问题就是就是在他删除了某张表之后,再次同步这张表的数据时,程序提示表已经存在,但是最终修复表格信息时确保了错,提示表格不存在。

我很容易就想到应该是表格判断那里出了问题。判断表格是否存在我使用的是DatabaseMetadata类下的getTables(),这个方法有四个参数,可以根据指定的参数从元数据中获取表格信息,理论上是不会出错的,毕竟是元数据,而且删除表格使用的Hue,删除没出任何问题,理论上元数据中的数据也应该删掉的:

 

public static boolean tableExist(String database, String table) throws SQLException {
  rs = connection.getMetaData().getTables(null, null, table ,null);
  return rs.next();
}

  

我针对那张表进行测试,发现返回的真的是true。

事实上,我对这个方法并不怎么熟悉,连这个判断的方法也是从网上查到的。

所以,为了解决这个问题,我开始研究这个方法。首先看这个方法的描述:

 

Retrieves a description of the tables available in the given catalog.Only table descriptions matching the catalog, schema, tablename and 
type criteria are returned.They are ordered by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM and TABLE_NAME. 

检索给定目录中可用表的说明。只返回与目录、架构、表名和类型条件匹配的表说明。它们按表类型、表类别、表计划和表名称排序。

 

 

它有四个参数:String catalog,String schemaPattern,String tableNamePattern,String[] types,分别表示:

 

catalog 包含目录名称的 String。对此参数提供 Null 值表示无需使用目录名称。
schema 包含架构名称模式的 String 值。对此参数提供 Null 值表示无需使用架构名称。
tableNamePattern 包含表名称模式的 String。
types 含有要包含的表类型的字符串数组。Null 表示应包含所有表类型。

  

最初我提供的参数是null, null, table ,null,即仅提供表名,因为当初查到的就是这样的,而且catalog和schema代表什么我也不清楚。

这种做法下在最初是没有什么问题的,但是到底为什么会导致查询出一张已经被删除的表?

我注意到了参数中的"tableNamePattern",而不是"tableName"或"table",所以是不是因为这个原因,它匹配到了其他表?

因为在Hive中我当初为了测试建立过几张副表(假设原表名为A,另外几张表是A2,A3等)。

所以我开始尝试替换掉"_",并且指定头尾(^ $ )进行精准匹配,然而反而任何表都匹配不到了。经过了数十分钟的测试,我最终认为原因应该不在这里。

 

getTables()方法的结果集中可能有以下列:
TABLE_CAT String=>表目录(可能为空)
TABLE_SCHEM String=>表架构(可能为空)
TABLE_NAME String=>表名
TABLE_TYPE String =>表类, 典型的类型有"TABLE","VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY","LOCAL TEMPORARY", "ALIAS", "SYNONYM"
REMARKS String => 表格注释
TYPE_CAT String => 目录类型(可能为空)
TYPE_SCHEM String => 架构类型(可能为空)
TYPE_NAME String => 类型名(可能为空)
SELF_REFERENCING_COL_NAME String => 类型表的指定“标识符”列的名称(可能为空)
REF_GENERATION String => 指定如何创建引用_col_name的inself_值。值为"SYSTEM", "USER", "DERIVED"(可能为空)

  

我在想,方法中匹配到的真的是那张表的信息吗?于是我编写了以下方法,输出所查询到的表的信息:

 

public static void tableData(String database, String table) throws SQLException {
  rs = connection.getMetaData().getTables(null, database, table ,null);
  while(rs.next()){
    System.out.println("==>"+rs.getString(1));
    System.out.println("==>"+rs.getString(2));
    System.out.println("==>"+rs.getString(3));
    System.out.println("==>"+rs.getString(4));
    System.out.println("==>"+rs.getString(5));
  }
}

  

输出如下(A为我所查询的表名):

  ==>
  ==>test   ==>A   ==>TABLE   ==>null

 

 

查询到的的确是这张表,但是这张表所在的库却是"test",我赶紧去test库中看了一下,发现里面真的存在一张A表,我这才想起来,这不是我当初写程序的时候创检测测试表吗?!!

闹了半天是被以前的自己坑了,但是这个问题也是很有价值的。

在输出中可以看到,第一列代表参数catalog,第二列代表参数schemaPattern,第三列代表参数tableNamePattern,第四列代表参数types。

所以参数schemaPattern应该指定为数据库,这样就能利用到我最初传入的参数database了。

将方法修改为:

 

public static boolean tableExist(String database, String table) throws SQLException {
  rs = connection.getMetaData().getTables(null, database, table ,null);
  return rs.next();
}

 

  

 

 

接着进行测试,发现果然返回了false!最终,在困扰了我两个多小时后,这个问题终于得以解决。

 

以上就是我在使用DatabaseMetadata.getTables()方法时遇到的一个小问题,希望能够给予大家帮助。

 

DatabaseMetadata.getTables()方法 问题记录

标签:str   删掉   turn   同步   types   数据   出错   检索   system   

原文地址:https://www.cnblogs.com/BlackString/p/11139186.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!