本教程解释了如何使用JDBC ResultSet来检索数据。 我们还将通过实例学习ResultSetMetaData和DatabaseMetaData接口:
在 JDBC DriverManager 的教程。 JDBC教程系列 我们学习了如何在Java应用程序中使用JDBC DriverManager和它的方法,JDBC PreparedStatement。
在本教程中,我们将讨论JDBC中的其余接口。 我们在之前的教程中已经介绍了Statement、PreparedStatement和CallableStatement接口。
在这里,我们将学习JDBC ResultSet、ResultSetMetaData和DatabaseMetaData接口,它们的方法以及如何在Java程序中使用这些方法。
JDBC结果集接口
ResultSet接口存在于java.sql包中。 它用于存储在Java程序中执行SQL语句后从数据库表中返回的数据。 ResultSet对象在结果数据上保持游标点。 默认情况下,游标位于结果数据的第一行之前。
next()方法用于将光标向前移动到下一个位置。 如果没有更多的记录,它将返回FALSE。 它通过使用任何一个语句对象调用executeQuery()方法来检索数据。 它可以是Statement或PreparedStatement或CallableStatement对象。 PreparedStatement和CallableStatement接口是语句的子接口。接口。
声明界面
Statement statemnt1 = conn.createStatement(); ResultSet rs1 = statemnt1.executeQuery("Select * from EMPLOYEE_DETAILS") ;
PreparedStatement接口
PreparedStatement pstatemnt1 = conn.prepareStatement(insert_query); ResultSet rs1 = pstatemnt1.executeQuery("Select * from EMPLOYEE_DETAILS") ;
我们可以使用getX()方法来获取列的数据,同时遍历结果,其中X-是列的数据类型。 我们可以使用列名或索引来使用getX()方法获取数值。
while(rs1.next() ) { int empNum = rs1.getInt("empNum"); String lastName = rs1.getString("lastName"); String firstName = rs1.getString("firstName"); String email = rs1.getString("email"); String deptNum = rs1.getString("deptNum"); String salary = rs1.getString("salary") ; System.out.println(empNum + " , " +lastName+ " , " +firstName+ " ," +email + " , " +deptNum + " ," +salary) ; }
我们也可以在getX()方法中提到列的索引号而不是列名。
while(rs1.next() ) { int empNum = rs1.getInt(1); String lastName = rs1.getString(2); String firstName = rs1.getString(3); String email = rs1.getString(4); String deptNum = rs1.getString(5); String salary = rs1.getString(6); System.out.println(empNum+", " +lastName+ ", " +firstName+ " , " +email+", " +deptNum +", " +salary); }
结果集类型
在默认情况下,我们可以在ResultSet中迭代数据/值,这些数据/值是作为执行的SQL语句的输出,在前进方向上。 我们可以使用Scrollable ResultSet在其他方向上迭代值。 我们可以在创建Statement、PreparedStatement和CallableStatement对象时指定ResultSet的类型和并发性。
结果集有3种类型,它们是:
- type_forward_only: 这是默认选项,光标从起点移动到终点,也就是沿着前进方向。
- type_scroll_insensitive: 在这种类型中,它将使光标向前和向后移动。 如果我们在迭代存储数据时对数据做了任何改变,那么如果有人改变了DB中的数据,它将不会在数据集中更新。 因为数据集拥有从SQL查询返回数据时开始的数据。
- type_scroll_sensitive: 它与TYPE_SCROLL_INSENSITIVE类似,不同的是如果有人在SQL查询返回数据后更新数据,在迭代的同时会反映数据集的变化。
结果集的并发性
在ResultSet中,有2种并发模式。 它们是:
- ResultSet.CONCUR_READ_ONLY: 这是默认的并发模式。 我们只能读取ResultSet中的数据。 更新是不适用的。
- ResultSet.CONCUR_UPDATABLE: 我们可以更新ResultSet对象中的数据。
有些数据库不支持所有ResultSet类型的并发模式。 在这种情况下,我们需要使用supportedResultSetConcurrency()方法检查它们是否支持我们所需的类型和并发模式。
结果集接口中的方法
有4类ResultSet方法,它们是:
- 航行方法
- 获取器方法
- 设定器方法
- 杂项方法
首先,我们将讨论导航方法,然后将进一步讨论。
#1)导航方法
这种方法是用来在数据集周围移动光标的。
- Boolean absolute(int row): 它用于将光标移动到参数中提到的指定行,如果操作成功则返回true,否则返回false。
- Void afterLast(): 它使ResultSet的光标在最后一行之后移动。
- Void beforeFirst(): 它使ResultSet的光标移到第一行之前。
- Boolean first(): 它使ResultSet的光标移动到第一行。 如果操作成功,返回True,否则返回False。
- Boolean last(): 它使ResultSet的光标移动到最后一行。 如果操作成功,返回True,否则返回False。
- Boolean next(): 它使ResultSet的光标移动到下一行。 如果有更多的记录,它返回True,如果没有更多的记录,返回False。
- Boolean previous(): 它使ResultSet的光标移动到前一行。 如果操作成功,返回True,否则返回False。
- Boolean relative(): 它将光标向前或向后移动到给定的行数上。
- Int getRow(): 它返回ResultSet对象现在所指向的当前行号。
- Void moveToCurrentRow(): 如果光标目前在插入行中,它会将光标移回当前行。
- Void moveToInsertRow(): 它将光标移动到特定的行,将该行插入到数据库中。 它记住了当前光标的位置。 因此我们可以使用moveToCurrentRow()方法将光标移动到插入后的当前行。
在本教程中,所有程序都是用Java编写的。 我们使用了Java 8版本和Oracle数据库。
>>你可以从这里下载Oracle软件。
>>你可以从这里下载Java 8版
它有一步步的Java安装过程。
JDBC结果集示例程序:(使用导航方法)
包 com.STH.JDBC; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class ResultSet_Example { public static void main(String[] args) throws ClassNotFoundException { // TODO 自动生成的方法桩 //选择查询 String select_query = "select * fromemployee_details"; Class.forName("oracle.jdbc.driver.OracleDriver"); //连接到Oracle数据库 try(Connection conn = DriverManager.getConnection("jdbc:oracle:thin:system/pass123@localhost:1521:X E") { //创建DatabaseMetaData对象 DatabaseMetaData dbmd = conn.getMetaData() ; //检查驱动程序是否支持滚动敏感类型和concur updatable boolean isSupportResultSetType =dbmd.supportsResultSetConcurrency(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); if(isSupportResultSetType == true) { // Creating prepared Statement PreparedStatement pstatemnt1 = conn.prepareStatement(select_query,ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet. CONCUR_UPDATABLE); ResultSet rs = pstatemnt1.executeQuery(); // Moving cursor to point first row rs.first() ;System.out.println("FIRST ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = "+ rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标移到最后一行 rs.last(); System.out.println("LAST ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = " + rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标移到第一行之前 rs.beforeFirst() ;System.out.println("光标指向第一行之前,使用 next() 向前移动"); //使用 next() 将光标移动到第一行 rs.next(); System.out.println("FIRST ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = " + rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标移到最后一行之后 rs.afterLast(); System.out.println("光标使用previous()向后移动"); //使用previous()将光标移动到最后一行 rs.previous(); System.out.println("LAST ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = "+ rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标移动到第三行 rs.absolute(3); System.out.println("光标正在指示第三行行"); System.out.println("THIRD ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = "+ rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标指向第三行的前一行 rs.relative(-1); System.out.println("光标正指向第三行的前1行"); System.out.println("Second ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = "+rs.getString(2)+"/n FIRST NAME = " + rs.getString(3)); //将光标移至第2行后的第4行 rs.relative(4); System.out.println("Cursor is pointing to the 4th row after the 2nd row"); System.out.println("SIXTH ROW \n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = " + rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //将光标移至当前一行。System.out.println(" 当前行 = " + rs.getRow()); } } catch (SQLException e) { e. printStackTrace(); } } }
输出:
在Employee_details表中的数据
解释一下:
在上面的程序中,我们在ResultSet中实现了first(), last(), beforeFirst(), afterLast(), next(), previous(), absolute(), relative()和getRow()方法。 为了使用这些方法,我们在prepareStatement方法中设置ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE数值。
接下来,我们将讨论什么是ResultSet中的Getter方法:
#2)获取器方法
ResultSet存储了数据库中表的数据,Getter方法用来获取ResultSet中表的值。 为此,我们需要传递列的索引值或列名。
以下是ResultSet中的getter方法:
- int getInt(int ColumnIndex): 它用于获取指定列Index的数据类型的值。
- float getFloat(int ColumnIndex): 它用于获取指定列Index的数值,作为浮动数据类型。
- java.sql.date getDate(int ColumnIndex): 它被用来获取指定列Index的值作为日期值。
- int getInt(String ColumnName): 它用于获取指定列的int数据类型的值。
- float getFloat(String ColumnName): 它用于获得指定列的浮动数据类型的值。
- Java.sql.date getDate(String ColumnName): 它用于获取指定列的日期值。
在ResultSet接口中,所有原始数据类型(布尔、长、双)和字符串都有getter方法。 我们也可以从数据库中获得数组和二进制类型的数据。 它也有相关的方法。
#3) 设置器/更新器方法
我们可以使用ResultSet Updater方法来更新数据库中的值。 它与Getter方法类似,但在这里我们需要传递数据库中特定列的值/数据来更新。
以下是ResultSet中的更新器方法:
- void updateInt(int ColumnIndex, int Value): 它用于用一个int值来更新指定列Index的值。
- void updateFloat(int ColumnIndex, float f): 它用于用浮动值更新指定列Index的值。
- void updateDate(int ColumnIndex, Date d): 它用于用日期值更新指定列Index的值。
- void updateInt(String ColumnName, int Value): 它用于用给定的int值来更新指定列的值。
- void updateFloat(String ColumnName, float f): 它用于用给定的浮动值更新指定列的值。
- Java.sql.date getDate(String ColumnName): 它用于用给定的日期值更新指定列的值。
在ResultSet接口中,有用于所有原始数据类型(Boolean, long, double)和String的Updater方法。
Updater方法只是更新ResultSet对象中的数据。 在调用insertRow或updateRow方法后,DB中的值将被更新。
更新一个行:
我们可以通过调用updateX()方法来更新行中的数据,传递列名或索引,以及需要更新的值。 我们可以在updateX方法中使用任何数据类型来代替X。 到目前为止,我们已经更新了ResultSet对象中的数据。 要更新DB中的数据,我们必须调用updateRow()方法。
插入一个行:
我们需要使用moveToInsertRow()来移动光标以插入新行。 我们已经在导航方法部分介绍了这一点。 接下来,我们需要调用updateX()方法来向该行添加数据。 我们应该为所有列提供数据,否则它将使用该特定列的默认值。
在更新数据后,我们需要调用insertRow()方法,然后使用moveToCurrentRow()方法,将光标位置移回到我们开始插入新行之前的那一行。
结果集实例:
包 com.STH.JDBC; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class ResultSet_Example1 { public static void main(String[] args) throws ClassNotFoundException { // TODO 自动生成的方法桩 String select_query ="select empnum,lastName,firstName from employee_details"; String insert_query = "insert into employee_details values(?,?,?,?,?)"; Class.forName("oracle.jdbc.driver.OracleDriver"); //Connecting to Oracle DB try(Connection conn = DriverManager.getConnection("jdbc:oracle:thin:system/pass123@localhost:1521:XE") { //Creating DatabaseMetaData objects DatabaseMetaData dbmd = conn.getMetaData() ;)//检查驱动程序是否支持滚动不敏感类型和并发更新 boolean isSupportResultSetType = dbmd.supportedResultSetConcurrency(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); if(isSupportResultSetType == true) { //创建准备好的语句 PreparedStatement pstatemnt1 =conn.prepareStatement(select_query,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE); ResultSet rs = pstatemnt1.executeQuery(select_query); //将光标移到点表的最后一行 rs.last(); System.out.println("最后一行:插入新雇员前"); System.out.println("最后一行:EMPNUM = " + rs.getInt(1) ); System.out.println("\n EMMP NUM = " + rs.getInt("empNum") + "\nLAST NAME = "+ rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); //设置在EMPLAYEE_DETAILS表中插入的值 //移动光标指向表插入一行 rs.moveToInsertRow(); //更新EMPNUM值 rs.updateInt(1, 1017); //更新LAST NAME值 rs.updateString(2, "Bond"); //更新 FIRST NAME值 rs.updateString(3, "James"); //插入一个新行 rs.insertRow() ;//将光标移至第5行 rs.absolute(5); System.out.println("Befor Updating EMPNUM of the 5th ROW"); System.out.println("\n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = " + rs.getString(2)+"\n FIRST NAME = " + rs.getString(3)); System.out.println(" Updateating EMP id of the 5th EMPLOYEE"); //Updating EMPNUM of 5th Row rs.updateInt(1,3005); rs.updateRow(); System.out.println("\n EMPNUM = " + rs.getInt("empNum") + "\n LAST NAME = "+ rs.getString(2)+ "\n FIRST NAME = " + rs.getString(3)); //将光标移至点最后一行 rs.last(); System.out.println("LAST ROW: EMPNUM = " + rs.getInt(1) ); System.out.println("\n EMP NUM = " + rs.getInt("empNum") + "\n LAST NAME = "+ rs.getString(2) + "\n FIRST NAME = " + rs.getString(3)); } catch (SQLLException e ) { e. printStackTrace(); } .}}
输出:
解释一下:
在上面的程序中,我们首先使用SELECT查询将Employee_details表的数据存储在ResultSet对象中。 然后,我们使用ResultSet的last()方法显示Employee_details表中最后一行的数据。 moveToInsertRow()方法使游标指向当前行,现在当前行就是最后一行。
updateXXX()方法用于更新行的值,insertRow()方法将数据插入到新的行中。 使用absolute()方法,我们使游标指向第5行。 UpdateInt()方法用于用表中第5个雇员的新ID更新EMPNUM。 之后,显示数据以检查EMPNUM是否被更新。
使用last()使游标指向表的最后一行,并显示出来。 为了执行上述逻辑,我们需要在prepareStatement方法中设置ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE值。
#4) 杂项方法
- void close(): 它用于关闭ResultSet实例并释放与ResultSet实例相关的资源。
- ResultSetMetaData getMetaData(): 它返回ResultSetMetaData实例。 它有关于查询输出的列的类型和属性的信息。 我们将在下一节学习更多关于ResultSetMetaData的内容。
结果集MetaData
什么是元数据?
元数据意味着关于数据的数据。 使用这个接口,我们将获得更多关于ResultSet的信息。 它在java.sql包中可用。 每个ResultSet对象都与一个ResultSetMetaData对象相关。
这个对象将有列的详细属性,如列的数据类型、列名、列数、表名、模式名等,我们可以使用ResultSet的getMetaData()方法获得ResultSetMetaData对象。
ResultSetMetaData的语法:
PreparedStatement pstatemnt1 = conn.prepareStatement(insert_query); ResultSet rs1 = pstatemnt1.executeQuery("Select * from EMPLOYEE_DETAILS"); ResultSetMetaData rsmd = rs.getMetaData() ;
ResultSetMetaData接口的重要方法:
方法名称 | 描述 |
---|---|
String getColumnName(int column) | 它返回特定列的列名 |
String getColumnTypeName(int column) | 它返回我们作为参数传递的特定列的数据类型。 |
String getTableName(int column) | 它返回列的表名 |
String getSchemaName(int column) | 它返回该列的表的模式名称 |
int getColumnCount() | 它返回结果集的列数。 |
boolean isAutoIncrement(int Column) | 如果给定的列是自动增量,它将返回true,否则返回false。 |
boolean isCaseSensitive(int Column) | 如果给定的列是大小写敏感的,它将返回true,否则返回false。 |
结果集MetaData实例
包 com.STH.JDBC; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; public class ResultSetMetaData_Example { public static void main(String[] args) throws ClassNotFoundException, SQLException { // TODO 自动生成的方法桩 String QUERY= " Select * fromemployee_details"; Class.forName("oracle.jdbc.driver.OracleDriver"); try(Connection conn = DriverManager.getConnection("jdbc:oracle:thin:system/pass123@localhost:1521:XE") { Statement statemnt1 = conn.createStatement(); ResultSet rs1 =null; rs1 = statemnt1.executeQuery(QUERY); ResultSetMetaData rsmd = rs1.getMetaData(); System.out.println(" We are using ResultSetMetaData " ) ;)System.out.println("列的数量:"+ rsmd.getColumnCount()); System.out.println("列1的列名:"+ rsmd.getColumnName(1)); System.out.println("列2的数据类型:" + rsmd.getColumnTypeName(2)); System.out.println("列1的表名称:" + rsmd.getTableName(1)); System.out.println("列1的计划表名称:" + rsmd.getSchemaName(1)); } } }
输出:
解释一下:
在上述程序中,我们在ResultSetMetaData接口中实现了getColumnCount()、getColumnName()、getColumnTypeName()、getTableName()和getSchemaName()方法。
数据库MetaData
DatabaseMetaData接口给出了关于数据库的信息,如DatabaseName,Database版本,等等。
DatabaseMetaData接口的重要方法:
方法名称 | 描述 |
---|---|
字符串getDriverName() | 它将返回我们在Java程序中使用的JDBC驱动程序的名称。 |
字符串getDriverVersion() | 它返回JDBC驱动程序的版本号 |
字符串 getUserName() | 它返回我们正在使用的数据库的用户名。 |
字符串 getDatabaseProductName() | 它返回我们正在使用的数据库的名称。 |
字符串 getDatabaseProductVersion() | 它返回我们正在使用的数据库的版本号。 |
结果集getSchemas() | 它返回连接的数据库中可用的模式名称。 |
字符串getStringFunctions() | 它返回连接的数据库中可用的字符串函数列表。 |
字符串getTimeDateFunctions() | 它返回所连接的数据库中可用的时间和日期功能的列表。 |
字符串 getURL() | 它返回数据库的URL |
Boolean isReadOnly() | 它返回数据库是否处于只读模式。 |
Boolean supportsBatchUpdates() | 它返回数据库是否支持批量更新 |
Boolean supportsSavepoints() | 它返回数据库是否支持保存点 |
Boolean supportsStatementPooling() | 它返回数据库是否支持语句池 |
Boolean supportsStoredProcedures() | 它返回数据库是否支持存储程序 |
Boolean supportsOuterJoins() | 它返回数据库是否支持外联接 |
在这里,我们列出了DatabaseMetaData接口的一些重要方法。 你可以参考官方网站的 甲骨文 在这里你可以看到DatabaseMetaData接口中的所有方法。
数据库MetaData示例:
包 com.STH.JDBC; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; public class DatabaseMetaData_Example { public static void main(String[] args) throws ClassNotFoundException, SQLException { // TODO 自动产生的方法桩Class.forName("oracle.jdbc.driver.OracleDriver"); Connection conn = DriverManager.getConnection("jdbc:oracle:thin:system/pass123@localhost:1521:XE"); DatabaseMetaData dbmd = conn.getMetaData(); System.out.println("Using DatabaseMetaData"); System.out.println("Driver Name: " + dbmd.getDriverName()); System.out.println("Driver Version: "+ dbmd.getDriverVersion()))数据库:" + dbmd.getUserName()); System.out.println("数据库产品名称:" + dbmd.getDatabaseProductName()); System.out.println("数据库产品版本:" + dbmd.getDatabaseProductVersion()); System.out.println("数据库中的字符串函数列表:" + dbmd.getStringFunctions()); System.out.println("时间& 日期数据库函数列表:" + dbmd.getTimeDateFunctions()) ;System.out.println("数据库的URL:" + dbmd.getURL()); System.out.println("数据库只读?" + dbmd.isReadOnly()); System.out.println("支持批量更新?" + dbmd.supportedBatchUpdates()); System.out.println("支持保存点?" + dbmd.supportedSavepoints()); System.out.println("支持 Statement Pooling?"+ dbmd.supportsStatementPooling())程序?" + dbmd.supportsStoredProcedures()); System.out.println("支持外层连接?"+ dbmd.supportsOuterJoins()); } }
输出:
解释一下:
在上述程序中,我们使用/实现了DatabaseMetaData接口中的getDriverName(), getDriverVersion(), getUserName(), getDatabaseProductName(), getDatabaseProductVersion(), getStringFunctions(), getTimeDateFunctions(), getURL(), isReadOnly(), supportsBatchUpdates(), supportsStatementPooling() , supportsSavepoints(), supportsStoredProcedures() 和 supportsOuterJoins() 方法。
应注意的事项:
- JDBC ResultSet接口用于存储数据库中的数据,并在我们的Java程序中使用它。
- 我们也可以使用ResultSet使用updateXXX()方法来更新数据。
- ResultSet对象将光标指向结果数据的第一行之前。 使用next()方法,我们可以在ResultSet中进行迭代。
- 我们有ResultSet的导航方法,可以在ResultSet对象中进一步移动
- ResultMetaData用于获取更多关于ResultSet的信息,如列名、列数、列的数据类型等。
- DatabaseMetData用于获取我们所连接的数据库的信息。
常见问题
问题#1)ResultSet的用途是什么?
答案是: ResultSet用于存储和检索数据库中的数据。 当executeQuery()方法执行后,它将返回ResultSet对象。 我们可以在程序中使用该ResultSet对象来执行逻辑。
问题#2)如何检查结果集是否为空?
答案是: 没有预定义的方法如length(), size()可以用来检查IsResultSet Empty。 我们可以使用next()方法进行迭代,如果它返回True,那么它不是空的,如果它返回False,意味着ResultSet是空的。
Q #3) ResultSet有可能是空的吗?
答案是: 不,executeQuery()方法返回的ResultSet对象可能永远不会为空。
问题#4)什么是可更新的结果集?
答案是: 一个可更新的ResultSet对象用于更新列中的数据,在列中插入数据和删除行。 为了使ResultSet成为一个可更新的对象,我们需要使滚动类型为敏感或不敏感,CONCUR类型为可更新。
结果集.TYPE_SCROLL_INSENSITIVE,结果集.CONCUR_UPDATABLE。
Q #5) 如何获得已连接的数据库名称?
答案是: 我们可以使用DatabaseMetaData对象的getDatabaseProductName()方法。
总结
在本教程中,我们讨论了什么是ResultSet、ResultSetMetaData和DatabaseMetaData接口,以及它们在JDBC程序中常用的重要方法。 我们还看到了如何使用ResultSet更新DB中的数据。 ResultSetMetadata包含有关ResultSet的信息,如列名、列数等等。
DatabaseMetaData包含数据库信息。
<;