Java JDBC 学习

来源:互联网 发布:洛阳正扬软件 编辑:程序博客网 时间:2024/06/03 13:47

说明

本篇文章重点介绍了使用JDBC API对数据库进行增删改查、执行存储过程中使用到的类和常用方法,不常用的并没有介绍,只能算作是对JDBC这部分知识的一个入门。还介绍了第三方数据库连接池DBCP和C3P0的代码实现。Java JDBC对数据库进行操作可分为四个步骤:
  1. 加载并注册驱动
  2. 获取Connection
  3. 操作数据库
  4. 关闭连接释放JDBC和数据库资源
这里主要介绍步骤2、3涉及到类和相关方法。在正式开始介绍之前我们需要了解一下SQL语言的分类。

SQL语言的分类


在使用JDBC API执行DQL总是返回一个结果集对象(ResultSet),执行DML总是返回受影响的行数,其它的语言大多数情况下返回0。

Connection的获取

获取Connection可以从实现了DataSource接口的数据库连接池获取,也可以通过DriverManager获取。我们先介绍一下java.slq.Conection接口,然后介绍通过连接池和DriverManager获取数据库连接。

java.sql.Connection接口

作用:代表与特定数据库的连接(会话),在连接上执行SQL并返回结果。
常用方法如下:
Statement createStatement() throws SQLException
创建一个Statement对象来将不带参数占位符的SQL发送到数据库执行。
PreparedStatement prepareStatement(String sql) throws SQLException
创建一个PreparedStatement对象将带参数占位符的SQL发送到数据库执行。PreperedStatement会预编译SQL,如果一个SQL需要重复执行多次使用PreparedStatement会提高执行效率。
CallableStatement prepareCall(String sql) throws SQLException
创建一个CallableStatement对象用于调用数据库的存储过程。

通过java.sql.DriverManager类获取Connection

作用:用于管理一组JDBC驱动程序。我们来看一下DriverManager的经典应用:
//加载mysql驱动类,并调用DriverManager.registerDriver()向DriverManager注册驱动实例
Class.forName(DBInfo.DIRVERCLASSNAME);Connection conn = DriverManager.getConnection(DBInfo.URL, DBInfo.USERNAME, DBInfo.PASSWORD);
我们可以在通过调用Class.forName("oracle的JDBC驱动")代码,向DriverManager注册oracle驱动实例,这样我们向DriverManger注册了mysql和oracle驱动实例,我们通过调用DriverManager.getConnection()会根据传入的url找到合适的驱动。JDBC规定URL的格式为jdbc:subprotocol:subname。
mysql url 事例:"jdbc:mysql://localhost:3306/jiemian_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true";
oracle url 事例:jdbc:oracle:thin:@192.168.9.87:1521:jrdb
代码:
/** * 通过java.sql.DriverManager获取Connection * @author Administrator * */public class ConnectionByDriverManager {public static Connection getConnection() throws Exception{Connection conn = null;try {//加载mysql驱动类,之后创建mysql创建实例,并向ManagerDrivers注册该实例 Class.forName(DBInfo.DIRVERCLASSNAME);conn = DriverManager.getConnection(DBInfo.URL, DBInfo.USERNAME, DBInfo.PASSWORD);System.out.println(conn!=null);}  catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();throw e;}return conn;}public static void main(String [] args){try {Connection conn = ConnectionByDriverManager.getConnection();conn.close();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

通过C3P0连接池获取Connection

spring框架使用的就是C3P0实现的数据库连接池。
package com.zhangxy.jdbcAPITest;import java.sql.Connection;import java.sql.SQLException;import com.mchange.v2.c3p0.ComboPooledDataSource;/** * 第三方数据库驱动C3P0实现的数据库连接池 * Spring的数据库连接池是使用C3P0实现的 * @author Administrator * */public class C3P0Pool {private static ComboPooledDataSource cpds=null;static {//C3P0读取指定目录下的c3p0-config.xml文件来实现连接池的配置//这里是编译后class所有在路径String path = C3P0Pool.class.getResource("").getFile()+"c3p0-config.xml";//System.out.println("path:"+path);//设置c3p0-config.xml文件读取的路径,如果不设置默认读取src目录下的c3p0-config.xml文件System.setProperty("com.mchange.v2.c3p0.cfg.xml",path);//ComboPooledDataSource(String configName),configName代表c3p0-config.xml文件中指定的named-config节点下的连接池初始化参数//如果不指定,将读取defalut-config节点下的连接池初始化参数cpds = new ComboPooledDataSource();}public static Connection getConnection() throws SQLException{return cpds.getConnection();}public static void main(String [] args){SQLException e1 = null;try {Connection conn = C3P0Pool.getConnection();conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke1=e;e.printStackTrace();}System.out.println("连接是否成功:"+(e1==null));}}


c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?><c3p0-config>        <default-config>            <property name="jdbcUrl">        jdbc:mysql://localhost:3306/jiemian_db           </property>            <property name="driverClass">com.mysql.jdbc.Driver</property>            <property name="user">root</property>            <property name="password">123456</property>                <property name="checkoutTimeout">3000</property>            <property name="idleConnectionTestPeriod">30</property>            <property name="initialPoolSize">10</property>            <property name="maxIdleTime">30</property>            <property name="maxPoolSize">100</property>            <property name="minPoolSize">10</property>            <property name="maxStatements">200</property>        </default-config>    <named-config name="test_db"><property name="jdbcUrl">jdbc:oracle:thin:@10.110.26.26:1521:crmdb4</property><property name="driverClass">oracle.jdbc.driver.OracleDriver</property><property name="user">dbmarketadm</property><property name="password">qwer5678</property><property name="checkoutTimeout">3000</property><property name="idleConnectionTestPeriod">30</property><property name="initialPoolSize">10</property><property name="maxIdleTime">30</property><property name="maxPoolSize">100</property><property name="minPoolSize">10</property><property name="maxStatements">200</property></named-config></c3p0-config>


c3p0读取c3p0-config参考:http://blog.csdn.net/soyuone/article/details/51554263

通过DBCP连接池获取Connection

package com.zhangxy.jdbcAPITest;import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.sql.Connection;import java.sql.SQLException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import org.apache.commons.dbcp.BasicDataSource;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;/** * 通过DBCP创建连接池 * DBCP并没有带有像C3P0一样可以从XML文件读取初始化连接池的配置,但是这里通过反射自己实现了这个功能 * @author Administrator * */public class DBCPPool {private static final String DBCP_CONFIG_PATH = DBCPPool.class.getResource("").getFile()+"dbcp-config.xml";private static BasicDataSource baseDs=null; static {init();}public static void init(){try {Class<?> clazz = Class.forName("org.apache.commons.dbcp.BasicDataSource");Object inst = clazz.newInstance();List<FieldInfo> list = getConfig();for(Iterator<FieldInfo> it = list.iterator();it.hasNext();){FieldInfo fieldInfo = it.next();String fName = fieldInfo.getName();String fValue = fieldInfo.getValue();String methodName = "set"+fName.substring(0,1).toUpperCase()+fName.substring(1, fName.length());Field properties = clazz.getDeclaredField(fName);Method method = clazz.getDeclaredMethod(methodName, properties.getType());method.invoke(inst, FieldInfo.getTrueTypeValue(fValue,properties.getType()));}baseDs = (BasicDataSource) inst;} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SecurityException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (NoSuchFieldException e) {// TODO Auto-generated catch blocke.printStackTrace();} }private static List<FieldInfo> getConfig(){List<FieldInfo> list = new ArrayList<FieldInfo>();File file = new File(DBCP_CONFIG_PATH);SAXReader reader = new SAXReader();try {Document doc = reader.read(file);Element rootEl = doc.getRootElement();for(Iterator<Element> it = rootEl.element("default-config").elementIterator("property");it.hasNext();){Element propertyEl = it.next();FieldInfo fieldInfo = new FieldInfo();fieldInfo.setName(propertyEl.attributeValue("name"));fieldInfo.setType(propertyEl.attributeValue("type"));fieldInfo.setValue(propertyEl.getTextTrim());//System.out.println(fieldInfo.toString());list.add(fieldInfo);}} catch (DocumentException e) {// TODO Auto-generated catch blocke.printStackTrace();}return list;}public static Connection getConnection() throws SQLException{return baseDs.getConnection();}public static void main(String [] args){//Object obj = 12;//System.out.print((obj instanceof String));try {Connection conn = DBCPPool.getConnection();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class FieldInfo{private String name;private String value;private String type;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getValue() {return value;}public void setValue(String value) {this.value = value;}public String getType() {return type;}public void setType(String type) {this.type = type;}@Overridepublic String toString() {return "name:"+getName()+" type:"+getType()+" value:"+getValue();}public static Object getTrueTypeValue(String value, Class<?> type){if(type == int.class||type==Integer.class){return Integer.valueOf(value);}else if(type==long.class||type==Long.class){return Long.valueOf(value);}else if(type==boolean.class||type==Boolean.class){return Boolean.valueOf(value);}return value;}}
dbcp-config.xml
<?xml version="1.0" encoding="UTF-8"?><dbcp-config>        <default-config>            <property type="string" name="url">        jdbc:mysql://localhost:3306/jiemian_db           </property>            <property name="driverClassName">com.mysql.jdbc.Driver</property>            <property name="username">root</property>            <property name="password">123456</property>                <property name="initialSize">30</property>            <property name="maxActive">20</property>            <property name="maxIdle">10</property>            <property name="minIdle">5</property>            <property name="maxWait">3000</property>         </default-config>    </dbcp-config>

第三方连接池都实现了javax.sql.DataSource接口

作用:用于获取DataSource代表的物理数据库的连接(Conection对象)。
该工厂用于提供到此 DataSource 对象所表示的物理数据源的连接。作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。实现 DataSource 接口的对象通常在基于 JavaTM Naming and Directory Interface (JNDI) API 的命名服务中注册。

DataSource 接口由驱动程序供应商实现。共有三种类型的实现:
  1. 基本实现 - 生成标准的 Connection 对象
  2. 连接池实现 - 生成自动参与连接池的 Connection 对象。此实现与中间层连接池管理器一起使用。
  3. 分布式事务实现 - 生成一个 Connection 对象,该对象可用于分布式事务,大多数情况下总是参与连接池。此实现与中间层事务管理器一起使用,大多数情况下总是与连接池管理器一起使用。
第三方连接池C3P0和DBCP都是实现了此接口,实现了以上中的第二种,其它两种有没有实现没有做了解。DataSource 对象的属性在必要时可以修改。例如,如果将数据源移动到另一个服务器,则可更改与服务器相关的属性。其优点在于,由于可以更改数据源的属性,所以任何访问该数据源的代码都无需更改。

通过 DataSource 对象访问的驱动程序本身不会向 DriverManager 注册。通过查找操作获取 DataSource 对象,然后使用该对象创建 Connection 对象。使用基本的实现,通过 DataSource 对象获取的连接与通过 DriverManager 设施获取的连接相同。
Connection getConnection() throws SQLException
尝试建立与此 DataSource 对象所表示的数据源的连接。
Connection getConnection(String username, String password)throws SQLException
尝试建立与此 DataSource 对象所表示的数据源的连接。

对数据库操作(增删改查)

对数据库进行操作有这么几个常用的接口和类:java.sql.Statement接口、java.sql.PreparedStatement接口(派生自Statemment接口)、java.sql.ResultSet接口,下面分别介绍。

java.sql.Statement接口

作用:用于执行静态SQL语句并返回生成结果集对象或者是受影响的行数。
方法:
1,int executeUpdate(String sql) throws SQLException
用于执行DML和DDL语言,对于DML语句返回受影响的行数,DDL语句返回0.
2,ResultSet executeQuery(String sql) throws SQLException
用于执行DQL语句,返回一个结果集对象。即使没有查询到结果也不会返回一个null,而是返回一个empty的ResultSet对象。
3,boolean execute() throws SQLException
执行指定的SQL语句,该语句可以是任何类型。返回true表示执行SQL是一个结果集,可以通过getResultSet()获取。false表示执行SQL是一个受影响的计数(通常执行的是DML语句)或无返回结果(通常执行的是DDL语句),可以通过getUpdateCount()获取。
4,boolean getMoreResults() throws SQLException
移动到当前Statement对象的下一个结果集。返回true表示表示当前位置是一个ResultSet对象,可以通过getResultSet()获取 。返回false表示当期是一个计数或没有更多结果,可以通过getUpdateCount()获取。如下表达式为true表示么有更多结果集:(statement.getMoreResultSets()==false && statement.getUpdateCount()==-1)
5,ResultSet getResultSet() throws SQLException
以ResultSet对象方式获取当前结果。
6,int getUpdateCount() throws SQLException
以受影响的行数方式获取当前结果。如果当前结果集为ResultSet形式或没有更多结果返回-1.

java.sql.PreparedStatement接口,派生自Statemment接口

作用:表示执行预编译的SQL语句返回生成结果集对象或者是受y影响的行数。
方法:
1,void setString(int parameterIndex,String x) throws SQLException
PreparedStatement接口有很多setXXXXX(index,x)方法,作用是给参数占位符设置java中类型的值。这里已setString()方法作为说明,index为参数占位符在SQL语句中的位置,从1开始,x代表要设置的值。

java.sql.ResultSet接口

作用:表示结果集,通常由执行select语句生产。 当我们查询得到一个ResultSet对象,这个对象不是在客户端的内存中存储所有查询到的数据,而是和数据库查询的表有个连接,调用next()遍历ResultSet是从数据库实时获取需要的列值。

1,boolean first() throws SQLException
将光标移动到ResutSet对象的第一行。如果光标有效返回true,否则返回false
2,boolean next() throws SQLException
将光标移动到下一行,如果存在下一行返回true,否则返回false。while(resultSet.next())可遍历ResultSet对象。一开始光标是在结果集第一行之前的,首次调用next()会将光标移动到第一行。当next()返回false光标在最后一行之后。

对数据库进行增删改查操作综合事例

package com.zhangxy.jdbcAPITest;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;public class OPStudent {public static void closeAll(Connection conn, Statement state, ResultSet rs){try {if(conn!=null&&!conn.isClosed()){conn.close();}if(state!=null&&!state.isClosed()){state.close();}if(rs!=null&&!rs.isClosed()){rs.close();}} catch (SQLException e) {e.printStackTrace();}}/** * 创建Student表 */public static void createStudentTable(Connection conn){Statement state = null;try {String dropTabSql = "drop table if exists student",createTabSql = "create table student(NO char(20),name varchar(20),primary key(NO))";state = conn.createStatement();//执行两条DDL语句,一下两行码执行时,没有抛出SQLException则证明执行成功state.executeUpdate(dropTabSql);state.executeUpdate(createTabSql);System.out.println("createStudentTable:成功。");} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{closeAll(conn,state,null);}}/** * 向Student表插入数据 * @param conn */public static void insertStudent(Connection conn){PreparedStatement pState = null;int c = 0;try {pState = conn.prepareStatement("insert into student(no,name) values(?,?)");pState.setString(1, "120000");pState.setString(2, "张三");c = pState.executeUpdate();System.out.println("insert into 受影响行数:"+c);pState.clearParameters();pState.setString(1, "130000");pState.setString(2, "李四");c = pState.executeUpdate();System.out.println("insert into 受影响行数:"+c);//如执行SQL条数很多建议使用批处理} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{closeAll(conn,pState,null);}}/** * 查询Student表数据 * @param conn */public static void queryStudent(Connection conn){Statement state = null;try {boolean isEmptyRs = true;state = conn.createStatement();ResultSet rs = state.executeQuery("select * from student");while (rs.next()) {isEmptyRs = false;String no = rs.getString("no");String name = rs.getString("name");System.out.println("no:"+no+" name:"+name);}//如果只想判断ResultSet是否是empty,不想遍历,可以使用一下代码//isEmptyRs=!rs.next();//光标移动到结果集的第一行,成功返回true,否则false//rs.previous();//光标移动到结果集第一行之前的位置System.out.println("查询没有结果:"+isEmptyRs);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{closeAll(conn,state,null);}}/** * 根据no更新Student表(使用参数占位符) * @param conn * @param no * @return */public static int updStudentByNo(Connection conn, String no, String name){int count=0;String sql = "update student t set t.name=? where t.no=?";try {PreparedStatement pState = conn.prepareStatement(sql);pState.setString(1, name);pState.setString(2, no);count = pState.executeUpdate();System.out.println(String.format("update student by no:[%s] name:[%s] 受营销的函数[%d]",no,name,count));} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return count;}public static void main(String [] args){try {createStudentTable( DBCPPool.getConnection() );insertStudent( DBCPPool.getConnection() );queryStudent( DBCPPool.getConnection() );updStudentByNo( DBCPPool.getConnection(), "120000", "abcefg");queryStudent( DBCPPool.getConnection() );} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}

JDBC API执行数据库的存储过程

JDBC API执行数据库存储过程主要涉及到java.sql.CallableStatement接口。

java.sql.CallableStatement接口

作用:用于调用存储过程。
调用存储过程的参数可以使用参数占位符.给存储过程的in参数传入值时,使用CallableStatement对象的set方法(例如pState.setString(1,"abc"))。给存储过程的out参数传入值时,使用CallabelStatement对象的registerOutParameter()方法向CallableStatement对象注册out参数,执行完存储过程之后,调用get方法获取返回的out参数。
JDBC API对调用的存储过程进行了转移,转义后对所有关系行数据库都能使用统一的方式调用存储过程,兼容所有数据库。义语法有一个包含结果参数的形式和一个不包含结果参数的形式。
 包含结果参数的:{?= call <procedure-name>[(<arg1>,<arg2>, ...)]},我在开发中使用的Mysql数据库,Mysql数据库的存储过程应该不能返回值(return 值),返回的值都是通过out参数带出,或者是使用select语句返回结果集。不知道其它数据库能不能返回一个值。
 不包含结果参数的:{call <procedure-name>[(<arg1>,<arg2>, ...)]}

执行数据库存储过程代码事例 

package com.zhangxy.jdbcAPITest;import java.sql.CallableStatement;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;/** * 利用CallableStatement调用数据库存储过程 * @author Administrator * */public class CallableStatementTest {/** * 调用带输入参数和输出参数的存储过程DROP PROCEDURE IF EXISTS `getsum`;DELIMITER ;;CREATE DEFINER = `root`@`localhost` PROCEDURE `getsum`(IN s1 int, IN s2 int, OUT r int)BEGINset r = s1+s2;END;;DELIMITER  */public static void callOne(){Connection conn = null;try {conn = DBCPPool.getConnection();String sql="{call getsum(?,?,?)}"; CallableStatement cState = conn.prepareCall(sql); cState.setInt(1, 100); cState.setInt(2, 200); cState.registerOutParameter(3, java.sql.Types.INTEGER);  cState.executeUpdate(); int result = cState.getInt(3); System.out.println("调用 getsum 存储过程结果为:"+result);} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(conn!=null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}/** * 调用返回结果集的存储过程 *  DROP PROCEDURE IF EXISTS `getstudent`;DELIMITER ;;CREATE DEFINER = `root`@`localhost` PROCEDURE `getstudent`(IN no int)BEGINselect * from student t where t.no=no;END;;DELIMITER ; */public static void call2(){Connection conn = null;try {conn = C3P0Pool.getConnection();CallableStatement pState = conn.prepareCall("{call getstudent(?)}");pState.setInt(1, 120000);ResultSet rs = pState.executeQuery();System.out.println("调用 getstudent 存储过程的结果为:");while(rs.next()){System.out.println("name:"+rs.getString("name"));}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally{if(conn!=null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}/** * 调用数据库函数 hello    DROP FUNCTION IF EXISTS `hello`;CREATE DEFINER = `root`@`localhost` FUNCTION `hello`(s CHAR(20))RETURNS char(50)RETURN CONCAT('Hello, ',s,'!'); */public static void callFunction(){Connection conn = null;try {conn = C3P0Pool.getConnection();PreparedStatement pState = conn.prepareStatement("select hello(?) as v");pState.setString(1, "abc");ResultSet rs = pState.executeQuery();while(rs.next()){System.out.println("调用数据库函数 hello 返回结果:"+rs.getString("v"));}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String [] args){callOne();call2();callFunction();}}

java.sql.ResultSetMetaData,(20170807补充)

ResultSetMetaData类可用于获取ResultSet对象中列的类型和属性信息对象。我们可以通过rs.getMetaData()对象来获取ResultSetMetaData对象。其实能去了解这个类是因为对一个问题的思考:我们使用java的ORM框架时,都需要创建一个对应的JavaBean来映射表的结构,发现myBatis从数据库中返回的可以不是一个JavaBean,而是一个Map或JSONObject,这这个两个对象的Key值都是和表字段名称一样的。感觉JDBC应该提供了响应的API来读取ResultSet对象列类型和属性的类,结果顺藤摸瓜就找到了ResultSetDetaData类。下面介绍一下此类常用的API。

  1. 获取指定位置的列所在表的名称。column参数为列所在的位置。注意这个位置是从1开始,而不是0。ResultSetMateData对象的所有方法参数列的位置都是从1开始。
String getTableName(int column) throws SQLException
  1. 返回ResultSet中的列数。
int getColumnCount() throws SQLException
  1. 按照指定的位置获取列的名称。
String getColumnName(int column) throws SQLException
  1. 按照指定的位置返回列在数据库中的类型。
String getColumnTypeName(int column)  throws SQLException
  1. 按照指定的位置返回列对应的java.sql.Types类中的类型。
int getColumnType(int column) throws SQLException
  1. 按照指定的位置返回列对应java编程语言中类的完全限定名称。
String getColumnClassName(int column) throws SQLException
  1. 指定列在表结构上是否可以为null。
int isNullable(int column) throws SQLException
  1. 按照指定列的位置返回该列的别名,通常由as指定。如果没有指定别名,此方法的返回值将和getColumnName()方法相同。
String getColumnLabel(int column) throws SQLException

下面给出一个综合事例:
public static void testResultSetMateData(Connection conn) {String sql = "select CONVERT(NO,SIGNED) no, NAME from student s where 1=2";//String sql = "select t.act_id from dbmarketadm.mk_actrecord_info t where t.act_id in ('201707285002064064')";Statement smt = null;ResultSet rs = null;java.sql.ResultSetMetaData rsmd = null;try {smt = conn.createStatement();rs = smt.executeQuery(sql);conn.getMetaData();rsmd = rs.getMetaData();String tableName = rsmd.getTableName(2);int columnCount = rsmd.getColumnCount();System.out.println("表名:" + tableName + ",查询结果为:" + columnCount);for (int i = 1; i <= columnCount; i++) {System.out.println("列名称:" + rsmd.getColumnName(i) + ",数据库类型:" + rsmd.getColumnTypeName(i) + ",sql数据库类型:"+ rsmd.getColumnType(i) + ",列别名(as):" + rsmd.getColumnLabel(i) + ",列是否为null:"+ rsmd.isNullable(i) + ",列类型对于的java类型:" + rsmd.getColumnClassName(i));}} catch (SQLException e) {e.printStackTrace();} finally {if (rs != null) {try {rs.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (smt != null) {try {smt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}

输出结果:
表名:student,查询结果为:2列名称:no,数据库类型:BIGINT,sql数据库类型:-5,列别名(as):no,列是否为null:0,列类型对于的java类型:java.lang.Long列名称:name,数据库类型:VARCHAR,sql数据库类型:12,列别名(as):NAME,列是否为null:1,列类型对于的java类型:java.lang.String







1 0
原创粉丝点击