通过 jdbc 分析数据库中的表结构和主键外键

在某项目中用到了 hibernate ,大家都知道 hibernate 是 ORM 框架,他是有能力根据实体生成数据库表的。我们在单元测试的时候用到了 dbUnit ,dbUnit 可以帮助我们在测试前把数据库的测试数据准备好,然后我们就利用现成的数据库环境测试,测试完成后需将数据库中的所有数据清除(为了不影响其他的单元测试),然后接着下一个测试。虽然已经有快一年多没更新了,dbUnit 整体使用还是不错的,但在清除数据的时候dbUnit 就似乎有些力不从心了。当表有自关联(表中有外键引用自己)的时候就有问题了,因为外键约束,数据总是不能清除。
dbUnit 不给力,那咱们自己可就要给力啊。学过 java 的人,应该也都学过 jdbc,jdbc 不仅可以操作数据库,还可以获取数据库中的 元(meta)信息,比如数据库中有哪些表,表中有哪些列等等。
我们要使用的核心类是 java.sql.DatabaseMetaData ,可以通过 java.sql.Connection#getMetaData() 来获得。

Connection conn = ...;
DatabaseMetaData dbMetaData = conn.getMetaData();


获取所有表

String catalog = conn.getCatalog(); //catalog 其实也就是数据库名
ResultSet tablesResultSet = dbMetaData.getTables(catalog,null,null,new String[]{"TABLE"});
while(tablesResultSet.next()){
String tableName = tablesResultSet.getString("TABLE_NAME");
}

tablesResultSet 中有以下列:
[list=1]
[*]TABLE_CAT String => 表类别(可为 null)
[*]TABLE_SCHEM String => 表模式(可为 null)
[*]TABLE_NAME String => 表名称
[*]TABLE_TYPE String => 表类型。典型的类型是 "TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM"。
[*]REMARKS String => 表的解释性注释
[*]TYPE_CAT String => 类型的类别(可为 null)
[*]TYPE_SCHEM String => 类型模式(可为 null)
[*]TYPE_NAME String => 类型名称(可为 null)
[*]SELF_REFERENCING_COL_NAME String => 有类型表的指定 "identifier" 列的名称(可为 null)
[*]REF_GENERATION String => 指定在 SELF_REFERENCING_COL_NAME 中创建值的方式。这些值为 "SYSTEM"、"USER" 和 "DERIVED"。(可能为 null)
[/list]

获取某个表的主键

String tableName = ...;
ResultSet primaryKeyResultSet = dbMetaData.getPrimaryKeys(catalog,null,tableName);
while(primaryKeyResultSet.next()){
String primaryKeyColumnName = primaryKeyResultSet.getString("COLUMN_NAME");
}

primayKeyResultSet 有以下几列:
[list=1]
[*]TABLE_CAT String => 表类别(可为 null)
[*]TABLE_SCHEM String => 表模式(可为 null)
[*]TABLE_NAME String => 表名称
[*]COLUMN_NAME String => 列名称
[*]KEY_SEQ short => 主键中的序列号(值 1 表示主键中的第一列,值 2 表示主键中的第二列)。
[*]PK_NAME String => 主键的名称(可为 null)
[/list]

获取某个表的外键

ResultSet foreignKeyResultSet = dbMetaData.getImportedKeys(catalog,null,tableName);
while(foreignKeyResultSet.next()){
String fkColumnName = foreignKeyResultSet.getString("FKCOLUMN_NAM");
String pkTablenName = foreignKeyResultSet.getString("PKTABLE_NAME");
String pkColumnName = foreignKeyResultSet.getString("PKCOLUMN_NAME");
}

foreignKeyResultSet 有以下几列:
[list=1]
[*]PKTABLE_CAT String => 被导入的主键表类别(可为 null)
[*]PKTABLE_SCHEM String => 被导入的主键表模式(可为 null)
[*]PKTABLE_NAME String => 被导入的主键表名称
[*]PKCOLUMN_NAME String => 被导入的主键列名称
[*]FKTABLE_CAT String => 外键表类别(可为 null)
[*]FKTABLE_SCHEM String => 外键表模式(可为 null)
[*]FKTABLE_NAME String => 外键表名称
[*]FKCOLUMN_NAME String => 外键列名称
[*]KEY_SEQ short => 外键中的序列号(值 1 表示外键中的第一列,值 2 表示外键中的第二列)
[*]UPDATE_RULE short => 更新主键时外键发生的变化
[*]DELETE_RULE short => 删除主键时外键发生的变化
[*]PK_NAME String => 主键的名称(可为 null)
[*]FK_NAME String => 外键的名称(可为 null)
[*]DEFERRABILITY short => 是否可以将对外键约束的评估延迟到提交时间
[/list]

关键的技术问题已经解决,接下来就该具体实施了。删除数据库中没有所以表中的数据,我想了一个简单粗暴的方法,就是0.先把所有表中的外键删除 1.删除表中的所有数据 2.把外键再加回去。


源代码在这里 [url=https://github.com/bastengao/jdbc-util]jdbc-util[/url]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值