通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类
http://www.cnblogs.com/lbangel/p/3487796.html
1、JDBC中通过MetaData来获取具体的表的相关信息。可以查询数据库中的有哪些表,表有哪些字段,字段的属性等等。MetaData中通过一系列getXXX函数,将这些信息存放到ResultSet里面,然后返回给用户。关于MetaData的说明网上也有不少,这里我只是从我自身学习的角度来记录一下简单使用JDBC以及获取数据表相关信息的方法。
DatabaseMetaData dbmd = con.getMetaData();
rs = dbmd.getColumns(con.getCatalog(), schema, tableName, null);
rs.getString(DATA_TYPE) // java.sql.Types 的 SQL 类型
rs.getString(COLUMN_SIZE) //列的大小。对于 char 或 date 类型,列的大小是最大字符数,对于 numeric 和 decimal 类型,列的大小就是精度。
rs.getString(DECIMAL_DIGITS) //小数部分的位数
2、下面就是我的JDBC下的获取表信息的代码了。我是以MySQL 5.0作为测试平台的。可以通过下面四个步骤来实现:

每个列描述都有以下列: TABLE_CAT String => 表类别(可为 null)
TABLE_SCHEM String => 表模式(可为 null)
TABLE_NAME String => 表名称
COLUMN_NAME String => 列名称
DATA_TYPE int => 来自 java.sql.Types 的 SQL 类型
TYPE_NAME String => 数据源依赖的类型名称,对于 UDT,该类型名称是完全限定的
COLUMN_SIZE int => 列的大小。
BUFFER_LENGTH 未被使用。
DECIMAL_DIGITS int => 小数部分的位数。对于 DECIMAL_DIGITS 不适用的数据类型,则返回 Null。
NUM_PREC_RADIX int => 基数(通常为 10 或 2)
NULLABLE int => 是否允许使用 NULL。
columnNoNulls - 可能不允许使用 NULL 值
columnNullable - 明确允许使用 NULL 值
columnNullableUnknown - 不知道是否可使用 null
REMARKS String => 描述列的注释(可为 null)
COLUMN_DEF String => 该列的默认值,当值在单引号内时应被解释为一个字符串(可为 null)
SQL_DATA_TYPE int => 未使用
SQL_DATETIME_SUB int => 未使用
CHAR_OCTET_LENGTH int => 对于 char 类型,该长度是列中的最大字节数
ORDINAL_POSITION int => 表中的列的索引(从 1 开始)
IS_NULLABLE String => ISO 规则用于确定列是否包括 null。
YES --- 如果参数可以包括 NULL
NO --- 如果参数不可以包括 NULL
空字符串 --- 如果不知道参数是否可以包括 null
SCOPE_CATLOG String => 表的类别,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
SCOPE_SCHEMA String => 表的模式,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
SCOPE_TABLE String => 表名称,它是引用属性的作用域(如果 DATA_TYPE 不是 REF,则为 null)
SOURCE_DATA_TYPE short => 不同类型或用户生成 Ref 类型、来自 java.sql.Types 的 SQL 类型的源类型(如果 DATA_TYPE 不是 DISTINCT 或用户生成的 REF,则为 null)
IS_AUTOINCREMENT String => 指示此列是否自动增加
YES --- 如果该列自动增加
NO --- 如果该列不自动增加
空字符串 --- 如果不能确定该列是否是自动增加参数
COLUMN_SIZE 列表示给定列的指定列大小。对于数值数据,这是最大精度。对于字符数据,这是字符长度。对于日期时间数据类型,这是 String 表示形式的字符长度(假定允许的最大小数秒组件的精度)。对于二进制数据,这是字节长度。对于 ROWID 数据类型,这是字节长度。对于列大小不适用的数据类型,则返回 Null。 参数:
catalog - 类别名称;它必须与存储在数据库中的类别名称匹配;该参数为 "" 表示获取没有类别的那些描述;为 null 则表示该类别名称不应该用于缩小搜索范围
schemaPattern - 模式名称的模式;它必须与存储在数据库中的模式名称匹配;该参数为 "" 表示获取没有模式的那些描述;为 null 则表示该模式名称不应该用于缩小搜索范围
tableNamePattern - 表名称模式;它必须与存储在数据库中的表名称匹配
columnNamePattern - 列名称模式;它必须与存储在数据库中的列名称匹配

3、获取所有表
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 中有以下列:

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)

4、某个表的主键
String tableName = ...;
ResultSet primaryKeyResultSet = dbMetaData.getPrimaryKeys(catalog,null,tableName);
while(primaryKeyResultSet.next()){
String primaryKeyColumnName = primaryKeyResultSet.getString("COLUMN_NAME");
}

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

5、某个表的外键
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 有以下几列: 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 => 是否可以将对外键约束的评估延迟到提交时间

6、应用:
大多数数据库有许多主键,但是在一个表中不允许两条记录的同一个主键具有相同的值。可以使用Java Database Connectivity(JDBC)来判断一个数据表的主键。 JDBC具有强大的元数据处理能力。java.sql.Connection类和java.sql.ResultSet类可以通过调用其getMetaData方法进行反射。可以通过下面两个方法:
//这两个方法都可以获取主外键信息,只是参照物不同
metaData.getExportedKeys("数据库名称", "schema", "表名");
metaData.getImportedKeys(catalog, null, tablename);
package cn.test;
import java.io.File;
import java.io.FileOutputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class TestAll {
private static String path = "D:\\tool\\project\\DynamicTable\\src\\cn\\test\\entity";
private static String pkname = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql://192.168.1.220:3306/Person";
private static String[] classNames = new String[] { "ShipStopping",
"ArriveShip", "TBLUserType" };
private static Map<String, String> fkTableNamesAndPk = new HashMap<String, String>();
public static void main(String[] args) {
test();
}
public static void test() {
Connection conn = null;
DatabaseMetaData metaData = null;
ResultSet rs = null;
ResultSet crs = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection(url, "admin", "123");
String catalog = conn.getCatalog(); // catalog 其实也就是数据库名
metaData = conn.getMetaData();
File dirFile = new File(path);
if (!dirFile.exists()) {
dirFile.mkdirs();
}
// 获取表
rs = metaData.getTables(null, "%", "%", new String[] { "TABLE" });
while (rs.next()) {
String tablename = rs.getString("TABLE_NAME");
String classname = getClassNameByTableName(tablename);
StringBuffer sb = new StringBuffer();
StringBuffer sbpackage = new StringBuffer();
sbpackage.append("package cn.test.entity;\r\n\r\n");
sbpackage.append("import javax.persistence.Column;\r\n");
sbpackage.append("import javax.persistence.Entity;\r\n");
sbpackage.append("import javax.persistence.GeneratedValue;\r\n");
sbpackage.append("import javax.persistence.Id;\r\n");
sbpackage.append("import javax.persistence.Table;\r\n\r\n");
sb.append("\r\n@Entity\r\n");
sb.append("@Table(name = \"" + tablename + "\")\r\n");
sb.append("public class " + classname
+ " implements java.io.Serializable {\r\n");
// 获取当前表的列
crs = metaData.getColumns(null, "%", tablename, "%");
// 获取被引用的表,它的主键就是当前表的外键
fkTableNamesAndPk.clear();
ResultSet foreignKeyResultSet = metaData.getImportedKeys(catalog, null, tablename);
while (foreignKeyResultSet.next()) {
String pkTablenName = foreignKeyResultSet.getString("PKTABLE_NAME"); // 外键表
String fkColumnName = foreignKeyResultSet.getString("FKCOLUMN_NAME"); // 外键
if (!fkTableNamesAndPk.containsKey(fkColumnName))
fkTableNamesAndPk.put(fkColumnName, pkTablenName);
}
// foreignKeyResultSet.close();
while (crs.next()) {
String columnname = crs.getString("COLUMN_NAME");
String columntype = crs.getString("TYPE_NAME");
System.out.println("--------------------------"+ columntype);
if (existFKColumn(columnname)) {
String fkclassname = getClassNameByTableName(fkTableNamesAndPk.get(columnname));
sbpackage.append("import " + pkname + "." + fkclassname+ ";\r\n");
sb.append("\t/** */\r\n");
sb.append("\tprivate " + fkclassname + " " + columnname+ ";\r\n");
} else {
sb.append("\t/** */\r\n");
sb.append("\tprivate "+ getFieldType(columntype, sbpackage) + " "+ columnname + ";\r\n");
}
}
sb.append("}");
File file = new File(dirFile, classname + ".java");
if (file.exists()) {
file.delete();
}
getTitle(sbpackage, classname);
FileOutputStream outputStream = new FileOutputStream(file);
outputStream.write(sbpackage.toString().getBytes());
outputStream.write(sb.toString().getBytes());
outputStream.close();
System.out.println(classname + " create success ... ");
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
try {
if (null != rs) {
rs.close();
}
if (null != conn) {
conn.close();
}
} catch (Exception e2) {
}
}
}
/**
* 根据表名获取类名称
*
* @param tablename
* @return
*/
private static String getClassNameByTableName(String tablename) {
String classname = getClassName(tablename);
for (String name : classNames) {
if (name.toLowerCase().equals(tablename.toLowerCase())) {
classname = name;
}
}
return classname;
}
private static boolean existFKColumn(String columnname) {
if (fkTableNamesAndPk != null) {
if (fkTableNamesAndPk.containsKey(columnname))
return true;
}
return false;
}
/**
* 适合表名为单个单词, 例如:表名是TBLUSER 类名是TBLUser;当表名是USER 类名是User;当表面是USERTYPE(两个单词)
* 时,类名是Usertype,如果要 UserType,将期望的类名添加到classNames字段中(与数据库表名一致 不区分大小写)。
*
* @param tablename
* @return
*/
public static String getClassName(String tablename) {
String res = tablename.toLowerCase();
if (tablename.startsWith("TBL")) {
return tablename.substring(0, 4) + res.substring(4);
}
return tablename.substring(0, 1).toUpperCase() + res.substring(1);
}
/**
* 设置字段类型 MySql数据类型
*
* @param columnType
* 列类型字符串
* @param sbpackage
* 封装包信息
* @return
*/
public static String getFieldType(String columnType, StringBuffer sbpackage) {
/*
* tinyblob tinyblob byte[]
tinytext varchar java.lang.string
blob blob byte[]
text varchar java.lang.string
mediumblob mediumblob byte[]
mediumtext varchar java.lang.string
longblob longblob byte[]
longtext varchar java.lang.string
enum('value1','value2',...) char java.lang.string
set('value1','value2',...) char java.lang.string
*/
columnType = columnType.toLowerCase();
if (columnType.equals("varchar") || columnType.equals("nvarchar")
|| columnType.equals("char")
// || columnType.equals("tinytext")
// || columnType.equals("text")
// || columnType.equals("mediumtext")
// || columnType.equals("longtext")
) {
return "String";
} else if (columnType.equals("tinyblob")
||columnType.equals("blob")
||columnType.equals("mediumblob")
||columnType.equals("longblob")) {
return "byte[]1111";
} else if (columnType.equals("datetime")
||columnType.equals("date")
||columnType.equals("timestamp")
||columnType.equals("time")
||columnType.equals("year")) {
sbpackage.append("import java.util.Date;\r\n");
return "Date";
} else if (columnType.equals("bit")
||columnType.equals("int")
||columnType.equals("tinyint")
||columnType.equals("smallint")
// ||columnType.equals("bool")
// ||columnType.equals("mediumint")
// ||columnType.equals("bigint")
) {
return "int";
} else if (columnType.equals("float")) {
return "Float";
} else if (columnType.equals("double")) {
return "Double";
} else if (columnType.equals("decimal")) {
// sbpackage.append("import java.math.BigDecimal;\r\n");
// return "BigDecimal";
}
return "ErrorType";
}
/**
* 设置类标题注释
*
* @param sbpackage
* @param className
*/
public static void getTitle(StringBuffer sbpackage, String className) {
SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
sbpackage.append("\r\n/**\r\n");
sbpackage.append("*\r\n");
sbpackage.append("* 标题: " + className + "<br/>\r\n");
sbpackage.append("* 说明: <br/>\r\n");
sbpackage.append("*\r\n");
sbpackage.append("* 作成信息: DATE: " + format.format(new Date())
+ " NAME: author\r\n");
sbpackage.append("*\r\n");
sbpackage.append("* 修改信息<br/>\r\n");
sbpackage.append("* 修改日期 修改者 修改ID 修改内容<br/>\r\n");
sbpackage.append("*\r\n");
sbpackage.append("*/\r\n");
}
}
通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类的更多相关文章
- 通过jdbc获取数据库中的表结构
通过jdbc获取数据库中的表结构 主键 各个表字段类型及应用生成实体类 1.JDBC中通过MetaData来获取具体的表的相关信息.可以查询数据库中的有哪些表,表有哪些字段,字段的属性等等.Met ...
- 两种获取MySql数据库中所有表的主键和外键约束信息的Sql语句
最近在写Rafy底层的一些东西,在数据库方面把MySql数据库集成到里面去,里面有一个需求,需要获取非系统数据库,也就是我们自己建立的数据库中所有表的主键和外键元数据列表. 第一种方法:是网上的方法, ...
- 通过 jdbc 分析数据库中的表结构和主键外键
文章转自:http://ivan4126.blog.163.com/blog/static/20949109220137753214811/ 在某项目中用到了 hibernate ,大家都知道 hib ...
- oracle数据库中的表设置主键自增
oracle中没有自增字段,可通过序列+触发器间接实现,cmd中sqlplus登录,直接运行即可.一般要经过一下几步: 1建立数据表 create table Test_Increase( ...
- SQL语句获取数据库中的表主键,自增列,所有列
SQL语句获取数据库中的表主键,自增列,所有列 获取表主键 1:SELECT TABLE_NAME,COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_U ...
- 查询SQLServer2005中某个数据库中的表结构、索引、视图、存储过程、触发器以及自定义函数
查询SQLServer2005中某个数据库中的表结构.索引.视图.存储过程.触发器以及自定义函数 2013-03-11 09:05:06| 分类: SQL SERVER|举报|字号 订阅 ( ...
- SQlServer 从系统表 sysobjects 中获取数据库中所有表或存储过程等对象
[sysobjects] 一.概述 系统对象表. 保存当前数据库的对象,如约束.默认值.日志.规则.存储过程等,该表中包含该数据库中的表 存储过程 视图等所有对象 在sqlserver2005,sql ...
- 使用sql查询mysql/oracle/sql server/gp数据库中指定表的字段信息(字段名/字段类型/字段长度/是否是主键/是否为空)
1,根据数据库类型拼接不同URL /** * 根据类型不同拼接连接的URL * @param dbType 1:mysql.2:oracle.3:sql server.4:gp * @param ip ...
- 如何通过phoenix中查看表的主键信息
需求描述: 今天一个开发的同事让帮忙查看下表的主键列,在此记录下. 操作过程: 1.通过!primarykeys命令查看表的主键 !primarykeys SYNC_BUSINESS_INFO_BYD ...
随机推荐
- UINavigationController 、UINavigationBar 、UINavigationItem 超清晰直观详解
UINavigationController 部分 1. UINavigationController 是一个容器类.里面盛放的是UIViewController. 容器的意思是,如果你不放入UIVi ...
- MEF在运行时替换插件
利用AppDomain的ShadowCopy特性. var setup = new AppDomainSetup { CachePath = cachePath, ShadowCopyFiles = ...
- CCBAnimationManager
#ifndef __CCB_CCBANIMATION_MANAGER_H__ #define __CCB_CCBANIMATION_MANAGER_H__ #include "cocos2d ...
- localhost,127.0.0.1 和 本机IP 三者的区别
localhost.127.0.0.1和本机IP的区别如下: 1.首先 localhost 是一个域名,在过去它指向 127.0.0.1 这个IP地址.在操作系统支持 ipv6 后,它同时还指向ipv ...
- Java类加载机制的理解
算上大学,尽管接触Java已经有4年时间并对基本的API算得上熟练应用,但是依旧觉得自己对于Java的特性依然是一知半解.要成为优秀的Java开发人员,需要深入了解Java平台的工作方式,其中类加载机 ...
- Material Designer的低版本兼容实现(六)—— Ripple Layout
新版的Android5.0添加了涟漪效果,虽然开源的库提供了各种控件便于大家使用涟漪效果.但是仍旧不可能满足所有需求,因此我今天改出来一个类叫做,LayoutRipple,其实感觉跟应该叫Ripple ...
- [Web 前端 ] 五大WEB主流浏览器及四大内核
现在国内常见的浏览器有:IE.Firefox.Safari.Opera.Google Chome.QQ浏览器.搜狗浏览器.百度浏览器.猎豹浏览器.UC浏览器.360浏览器.遨游浏览器.世界之窗浏览器等 ...
- [Hook] 免root,自己进程内,startActivity hook的几种姿势
首先关于startActivity 我们平时会经常使用到 在activity内 直接startActivity(intent) 其实这里还有一种start方式 我们可能没怎么用过 getApplica ...
- 可重入读写锁ReentrantReadWriteLock基本原理分析
前言 本篇适用于了解ReentrantLock或ReentrantReadWriteLock的使用,但想要进一步了解原理的读者.见于之前的分析都是借鉴大量的JDK源码,这次以流程图的形式代替源码,希望 ...
- spring学习之@SessionAttributes
一.@ModelAttribute 在默认情况下,ModelMap 中的属性作用域是 request 级别是,也就是说,当本次请求结束后,ModelMap 中的属性将销毁.如果希望在多个请求中共享 M ...