扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:builder.com.cn 2007年3月5日
关键字:
连接数据库
为了写出适用于任何RDBMS的JDBC代码,首先有必要为该RDBMS获得和安装一个驱动程序等级。对于大部分知名的RDBMSs都有驱动程序:比如,你可以获得一个Oracle JDBC驱动程序(Oracle JDBC driver)或MySQL驱动程序(MySQL driver)。为你的特别数据库获得驱动程序,并确保在你的Java类途径(CLASSPATH)中可用。
接着,配置RDBMS访问,通过配置文件可以获得关于服务器域名,访问用户名以及密码的信息。该文件应该名为Connection.properties,并且可能有如下版本:
driverName=the driver name
url=url for connection
userName=user name
password=password
因此,对于Oracle,你可能看到:
driverName=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@host:1521:db1
userName=user
password=pass
而对于MySQL,你可能看到:
driverName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1
userName=user
password=pass
找回及处理查询结果
完成了以上所有步骤,让我开始写代码。我们将从基础开始:执行一个SELECT *查询以及处理查询结果。让我们开始写一些代码(列表A)来为数据库创建和返回一个连接。
表 A
package jdbc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.PropertyResourceBundle;
import java.util.ResourceBundle;
/**本类程序将加载驱动并根据当前值连接数据库。文件中,将为创建一个连接对象建立一种方法。返回
/
public class DatabaseConnector
{
/** This variable will hold the value for driver name.*/
String driverName = null;
/**
* This variable will hold the value for a database url of the form
* jdbc:subprotocol:subname
*/
String url = null;
/**
* This variable will hold the value for the database user on whose behalf
* the connection is being made
*/
?String userName = null;
/**
* This variable will hold the value for the user's password?
*/
String password = null;
/**
* The constructor reads the property file and populates variables
*/
public DatabaseConnector()
{
try
{
InputStream is = new FileInputStream("Connection.properties");
ResourceBundle bundle = new PropertyResourceBundle(is);?driverName = (String) bundle.getObject("driverName");
url = (String) bundle.getObject("url");
userName = (String) bundle.getObject("userName");
password = (String) bundle.getObject("password");
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* This method will create a connection and return it.
* @return a connection to the URL
*/
public Connection getConnection()
{
Connection conn = null;
try
{
// Loading the driver
Class.forName(driverName);
// Creating connection
conn = DriverManager.getConnection(url, userName, password);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (SQLException e)
{
e.printStackTrace();
}
return conn;
}
}
在本类中,getConnection()用于创建一个普通连接对象,在Connection.properties配置文件中使用指定的访问参数和驱动程序。如果存在连接问题——例如,如果用户名或密码不正确——以上代码将生成例外。在使用本类之前,记住修改代码以反映你的系统中真实的配置文件路径。
接着是一种类执行SELECT查询并处理结果。(列表B)
表B
package jdbc;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
? This class will read and print the contents of a table
?
?/
public class DataSelector
{
public static void main(String[] args)
{
DataSelector ds = new DataSelector();
ds.select();
}
/**
* This method will select all rows and print them to the console.
*
*/
private void select()
{
int id = 0;
float temp = 0.0F;
String cityName = null;
String query = "SELECT ID, CITY, TEMP FROM CITY_TEMP";
try
{
// Creating statement and executing the query
Connection conn = new DatabaseConnector().getConnection();
tatement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(query);
while(rs.next())
{
id = rs.getInt(1);
cityName = rs.getString(2);
temp = rs.getFloat(3);
System.out.println(id + ", " + cityName + ", " + temp);
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
本类首先使用DatabaseConnector类来打开到数据库的连接。然后创建一个Statement对象,这揭示了一个executeQuery()方式。然后一个简单的SELECT查询被传送给executeQuery()方法,其返回一个Resultset对象,代表查询的结果。一个while循环,结合对象的next()方法,然后被用于重述结果设置,打印每个域的值。注意getString(), getInt()和getFloat()方法被用于访问不同结果设置的数据类型,与传给的每个场指数作为意见。
技巧:你可以用域名代替域索引来获得相同结果。例如,在前个列表中,方法调回getFloat("temp")与调回getFloat(3)结果相同。
以下是前个列表的输出结果:
1, LONDON, 8.8
2, MUMBAI, 22.0
3, NEW YORK, 2.5
4, PARIS, 12.6
5, SYDNEY, 25.3
6, TOKYO, 5.7
7, DEHLI, 36.2
8, BERLIN, 10.1
9, BAGHDAD, 34.4
10, RANGOON, 23.9
增加新记录
你在前个列表中看到的Statement对象也揭示了一种executeUpdate()方法,这可以用来特别方便地增加新记录(或更新已有的记录)。为了看到实际效果,参见列表C,这定义了一种新insert()方法来执行一个INSERT查询,以及向列表添加一个新记录。
表C
package jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
? This class will insert a row in the table and print a message
? if successful
?
?/
public class DataInserter
{
public static void main(String[] args)
{
DataInserter ds = new DataInserter();
int result = ds.insert();
if(result != 0)
{
System.out.println(result + " row(s) inserted successfully.");
else
{
System.out.println("Data could not be inserted.");
}
}
/**
* This method will insert a row and return an integer value
* specifying the number of rows inserted.?
* @return no of rows inserted
*/
private int insert()
{
int id = 13;
int result = 0;
float temp = 4.5F;
String cityName = "CALCUTTA";
String query = "INSERT INTO CITY_TEMP VALUES ("+ id + ", '" +
ityName + "', "+ temp+")";
try
{
// Creating statement and executing the query
Connection conn = new DatabaseConnector().getConnection();
Statement stmt = conn.createStatement();
esult = stmt.executeUpdate(query);
}
catch (SQLException e)
{
e.printStackTrace();
}
return result;
}
}
内部的insert()方法相当具有自我说明性:几个变量,代表被增加的新数据,已向查询串进行初始化和以内插值替换。一个新的连接和陈述对象也被创立,并且Statement对象的executeUpdate()方法被用于产生查询串。接着一个信息被打印到控制台,指示增加动作是否成功以及更新的列数。如果发生错误——例如,尝试更改记录ID至已使用的——一个例外以及堆栈跟踪将产生。
更新和删除存在的记录
更新或删除存在的记录是相似的过程:初始化一个Statement对象,然后传递对象的executeUpdate()方法一个恰当的更新或删除查询。列表D是例子。
表D
package jdbc;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
? This class will update the table and a print a message if it
? was successfully updated.
?
?/
public class DataModifier
{
public static void main(String[] args)
{
DataModifier ds = new DataModifier();
int result = ds.update();
if(result != 0)
{
System.out.println(result + " row(s) updated successfully.");
}
else
{
System.out.println("Data could not be updated.");
}
}
/**
* This method will update table and return an integer value
* specifying the number of rows updated.?
*
* @return no of rows updated
*/
private int update()
{
int id = 20;
int result = 0;
float temp = 32.9F;
String query = "UPDATE CITY_TEMP SET TEMP=" + temp + " WHERE ID = "+ id;
try
{
// creating statement and executing the query
Connection conn = new DatabaseConnector().getConnection();
Statement stmt = conn.createStatement();
result = stmt.executeUpdate(query);
}
catch (SQLException e)
{
e.printStackTrace();
}
return result;
}
}
在此,executeUpdate()方法将更新表格并返回一个整数值,指定更新的行数。一个有趣的事情是:因为可以写一个更新或删除查询,可以在不实际改变表格的情况下成功——例如,一个更新查询涉及一个不存在记录ID——你的代码应该检查这个返回值(如上述列表所示)并返回一个恰当的信息。
获得数据库和表格信息
JDBC也可以让你在一个RDBMS中获得有关数据库和表格的元信息。这包含基本信息,比如表名称和类型,以及更高级的信息,比如表数据类型,关键词,域名和局限。对于这个信息的关键是DatabaseMetaData对象,列表E对此加以说明。
表E
package jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
? This class provides information related to the database. It shows
? how the Java API can be used to retrieve database information.
?/
public class DatabaseUtil
{
public static void main(String[] args)
{
DatabaseUtil dbUtil = new DatabaseUtil();
dbUtil.getDatebaseInfo();
}
/**
* This method gets information related to the database.
* It returns the following output
* Schema Name
*Table Name (number of rows)
*
*/
private void getDatebaseInfo()
{
try
{
// Getting DatabaseMetaData instance
DatabaseConnector dc = new DatabaseConnector();
Connection conn = dc.getConnection();
DatabaseMetaData dmd = conn.getMetaData();
String tableName = null;
String schemaName = null;
String query = "SELECT COUNT(*) FROM ";
// Retrieving the schema names
ResultSet rsOfSchemas = dmd.getSchemas();
Statement stmt = conn.createStatement();
while(rsOfSchemas.next())
{
schemaName=rsOfSchemas.getString("TABLE_SCHEM");
System.out.println(schemaName);
/ Retrieving the table names
ResultSet rsOfTables = dmd.getTables(null,schemaName,null,new String[]{"TABLE"});
while(rsOfTables.next())
{
tableName = rsOfTables.getString("TABLE_NAME");
// Retrieving the number of rows in a table
ResultSet rsOfNoOfRows = stmt.executeQuery(query + tableName);
while(rsOfNoOfRows.next())
{
int nofOfRows = rsOfNoOfRows.getInt(1);
System.out.println("\t" + tableName + "(" + nofOfRows +")");
}
}
}
}
catch (SQLException e)
{
e.printStackTrace();
}
}
}
本类使用了两种方法,由DatabaseMetaData对象揭示:getSchemas(),这在可用的数据库或计划上返回信息,和getTables(),能够使用一个标准while()循环来处理。以上类的应用也尝试在每个表中返回一些有关记录数字的信息,通过在每个表中执行SELECT COUNT(*)查询,由getTables()返回。
表F是输出的例子:
表F
USR1
EMP(7)
DEPT(2)
USR2
TEMP(1)
T1(0)
USR3
USR5
CITY_TEMP(11)
XENON(43)
DatabaseMetaData对象也揭示了几个其它有用的方法:getColumns()为域信息;getColumnPrivileges()为域访问权;getDefaultTransactionIsolation()为处理隔离水平;getIndexInfo()为有关一个表的索引信息;getProcedures()为一个可用的存储程序表;getUserName()为目前登陆的用户姓名;以及很多其它信息。阅读更多可用方法在Sun Web site.
注意:要记住不同的数据库系统有不同的性能,因此很可能这些方法中不适用于你的特殊RDBMS上。查看你的RDBMS驱动文件,获得哪些方法是被支持的信息。
这就是本指南的内容。你下次坐下来写一个数据库驱动Java应用程序的时候,上述类模板将为你节省很多时间。祝编程愉快!
责任编辑:德东
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者