从 ResultSet Java 中获取主键列
Posted
技术标签:
【中文标题】从 ResultSet Java 中获取主键列【英文标题】:Get Primary Key Column from ResultSet Java 【发布时间】:2014-02-15 04:38:20 【问题描述】:我正在尝试从 ResultSet 中获取表的主键列。以下是步骤
我关注了:
1. SQL QUERY: Select id,subid,email,empname from Employee
2. Executed this from java.sql.Statement and got the Results in ResultSet.
这是有趣的部分。
3. ResultSetMetadata rsmd = rs.getMetadata();
现在,如果我观察这个变量 "rsmd" ,它会显示相关列名的主键标志,但我无法访问它或将它放入任何变量中。
我需要帮助。
注意:我不想使用 DatabaseMetadata 及其 getPrimaryKeys() 函数,因为它会对外部数据库产生额外的影响。此外,ResultSetMetadata 对象已经拥有我只需要获取的主键信息。
【问题讨论】:
查看ResultSetMetaData
docs.oracle.com/javase/7/docs/api/java/sql/…的文档
【参考方案1】:
关于您的问题的一些想法以及解决方案(希望对您有所帮助):
在我使用在结果集元数据中具有主键信息的结果集的一生中,我没有想到这一点。
在我看来这甚至很奇怪,因为原则上,结果集不仅限于显示仅在一个表的列中组织的行,也没有强制显示一个表的所有列,甚至列可能不是表列。
例如,我们可能会发出类似的查询
select X.a, X.b, Y.n, Y.m, 'bla'||X.c||'blub'||Y.l from X, Y;
在这种情况下,我们可能有也可能没有来自一个或两个表的主列,或者没有一个。
您已经知道标准ResultSetMetaData
-接口不提供主键信息访问。您在调试器中看到的是实现该接口的类的实例。
有几种方法可以处理您的任务:
(不是我喜欢的方式)
投射到具体实现ResultSetMetaData
-class 并访问
主键信息(如果可用)。但请注意,并非每个ResultSetMetaData
实现都提供此信息。
(更多架构方法,我这边也没有提出,但需要 如果我们处理不完整的 JDBC 驱动程序) 利用您使用的不同数据库的系统表 但当然将其隐藏在抽象中,例如桥接模式。 根据您获得的赠款,通常没什么大不了的 (包括测试基础架构部分最多 4 人天的工作和大约 1 人天的测试 您要访问的每个数据库系统) 然后,您可以从那里获得任何所需的元数据信息,包括有关外键关系的信息。
(我的工作)
只需使用java.sql.DatabaseMetaData
-class
它为每个可访问的表提供了您所需的主键信息。
这里是代码-sn-p(在 Java 7 中):
public static Set<String> getPrimaryKeyColumnsForTable(Connection connection, String tableName) throws SQLException
try(ResultSet pkColumns= connection.getMetaData().getPrimaryKeys(null,null,tableName);)
SortedSet<String> pkColumnSet = new TreeSet<>();
while(pkColumns.next())
String pkColumnName = pkColumns.getString("COLUMN_NAME");
Integer pkPosition = pkColumns.getInt("KEY_SEQ");
out.println(""+pkColumnName+" is the "+pkPosition+". column of the primary key of the table "+tableName);
pkColumnSet.add(pkColumnName);
return pkColumnSet;
【讨论】:
【参考方案2】:我想使用ResultSet
检查表中的列是否是主键。
在mysql JDBC驱动中,如果仔细观察,java.sql.ResultSetMetaData
的真正实现类应该是com.mysql.jdbc.ResultSetMetaData
类。这个类提供了一个protected
方法来获取每个字段的信息
protected Field getField(int columnIndex) throws SQLException
此方法可以为您提供每个 column
索引的 Field
实例。 使用 Field 实例,您可以获取 Field 的属性。要检查它是否是主键,您可以调用
Field.isPrimaryKey()
在您的类型转换中使用 com.mysql.jdbc.ResultSetMetaData
的 FQN,例如 ((com.mysql.jdbc.ResultSetMetaData) rsmd).getField(i).isPrimaryKey()
。这是因为您无法导入两个同名的类文件并在整个文件中使用它们
请阅读 MySql JDBC API 中Field 的文档以了解更多信息。希望这会有所帮助!
【讨论】:
我在评估 ResultSetMetadata 对象时也尝试过。这只有在评估时才有效,你能详细描述一下如何得到它吗?我试过:((ResultSetMetadata)rsmd).getField(i).isPrimaryKey()错误:无法解析函数getField()(可能是因为它受保护) 这是因为您的类文件中已经导入了 java.sql.ResultSetMetaData。在您的类型转换中使用 com.mysql.jdbc.ResultSetMetaData 的 FQN,例如((com.mysql.jdbc.ResultSetMetaData) rsmd).getField(i).isPrimaryKey()
。请告诉我会发生什么
是的,它的工作。你是对的,我明白了我的 IDEA IDE 之所以会因此而出人意料的原因。但是我必须检查 DB2、Oracle、Teradata API 是否存在 ResultSetMetadata 类,因为我的程序支持 7 个以上的数据库
@SID 不客气 :) 请接受答案,让其他人知道它有效。
@Keerthivasan 不,这是行不通的。当方法受到保护时,您的类应该是该方法的子类或在同一个包中。但你的方法值得赞赏。你可以使用反射来完成这项工作。 method = com.mysql.jdbc.ResultSetMetaData.class.getDeclaredMethod("getField", int.class); method.setAccessible(true); com.mysql.jdbc.Field field = (com.mysql.jdbc.Field) method.invoke(resultSetMetaData, x); System.out.println(field.isPrimaryKey());
【参考方案3】:
使用@Keerthivasan Approach 这里是完整的工作代码。唯一的问题是答案不能使用这样的方法,因为它是protected
方法。
这是工作代码。
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
int count = resultSetMetaData.getColumnCount();
for (int x = 1; x <= count; x++)
Method method = null;
try
method = com.mysql.jdbc.ResultSetMetaData.class.getDeclaredMethod("getField", int.class);
method.setAccessible(true);
com.mysql.jdbc.Field field = (com.mysql.jdbc.Field) method.invoke(resultSetMetaData, x);
if (field.isPrimaryKey())
System.out.println("-----------PK---------------------");
else
System.out.println("+++++++++++++++NPK++++++++++++++++++");
catch (NoSuchMethodException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InvocationTargetException e)
e.printStackTrace();
【讨论】:
这是完美的。【参考方案4】: // find primary keys
try
ResultSet rs = conn.getMetaData().getPrimaryKeys(null, conn.getSchema(), table);
while (rs.next())
System.out.println(rs.getString("COLUMN_NAME") + ":" + rs.getString("KEY_SEQ"));
catch (SQLException e)
e.printStackTrace();
这适用于所有 RDBMS,而不仅仅是 MSSQL
【讨论】:
以上是关于从 ResultSet Java 中获取主键列的主要内容,如果未能解决你的问题,请参考以下文章
sql server 中 怎么让自动增1的主键列 临时的 让它可以手动插入指定值?