连接数据库
1.什么是JDBC
JDBC(Java Database Connectivity)API 是组成Java数据库连接性的一组类,它们是Java2标准平台版本的一部分,使用它时不需要下载额外的部件或修改类路径。JDBC提供了Java程序与多种数据库通讯的途径,而不需要编写任意与平台有关的代码来实现这种通讯。
JDBC抽象了各个数据库厂商的详细资料,并且概括了大多数常见的数据库访问函数,其结果是产生了一套包含在java.sql和java.text包中的方法。这些方法能够用在任意一个数据库上,它们通过与厂商有关的JDBC驱动程序提供JDBC连接。
2.JDBC驱动程序的类型
所有的JDBC驱动程序都属于四种类型之一。
类型一:
这种类型的驱动程序定义了随Java2平台出现的JDBC到ODBC桥。该驱动程序把标准JDBC调用翻译成对应的ODBC调用,并借助操作系统的ODBC库把它发送到ODBC数据源。这种方法效率低下,并且使用范围有限,并不是最好的解决方案,但在某些情况下,它仍然是唯一的解决方案:例只能使用JDBC-ODBC桥访问微软的Access数据库。
类型二:
第2种JDBC驱动程序将使用Java驱动程序(部分Java代码,部分本机代码)同厂商有关的API进行通讯。使用这种驱动程序访问数据库时,驱动程序把请求翻译成厂商API能够理解的请求,数据库处理该请求并把处理结果通过API发送回JDBC驱动程序, 再由JDBC驱动程序将结果转换成JDBC标准的格式来返回给应用程序。
类型三:
第3类型JDBC驱动程序利用纯Java驱动程序和all-java中间层(中间件?)为应用提供数据访问。Java程序发送JDBC调用时,先通过JDBC驱动程序,而后不需翻译直接发送到中间层,再由中间层调用另外的驱动程序(第1类或第2类驱动程序)处理并完成请求。
类型四:
第4类型驱动程序是一种将请求直接发送给数据库的纯Java驱动程序,是最有效的数据库访问方法。它不必使用额外的程序库(API)或安装中间件。
3.JDBC API
组成 JDBC API 的类和接口包含在java.sql和java.text包中。
(1)建立连接:
首先必须使用Class.forName(String dbDriverClassname)方法检查是否安装了适当的JDBC驱动程序。这个方法是用来动态加载类的,dbDriverClassname是驱动程序类的名称。加载了驱动程序后,使用java.sql包中的DriverManager类中的getConnection()方法可以建立数据库连接,这个方法有三种形式:
public static synchronized Connection getConnection(String url) throws SQLException
public static synchronized Connection getConnection(String url,String user,String pwd) throws SQLException
public static synchronized Connection getConnection(String url, java.util.Properties info) throws SQLException
(2)执行SQL语句并取回结果:
◎ 创建了数据库连接后,当我向数据库库发出一个SQL查询时,首先要做的事情是使用Connection对象的方法创建一个Statement、PreparedStatement或者CallableStatemet;一旦有了这些语句(statement)对象中的任一个,就可以执行该语句并通过ResultSet对象读出查询结果(如果查询有返回结果的话)。
Statement createStatement() throws SQLException
Statement createStatement(int resultSetType , int resultSetConcurrency) throws SQLException
PreparedStatement prepareStatement(String sql) throws SQLException
PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
CallableStatement prepareCall(String sql) throws SQLException
CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
以上方法中的resultSetType参数决定能否向后滚动结果集,resultSetConcurrency参数决定是否可以修改结果集。ResultSet接口中的以下常数值定义了上面每个方法能够使用的值:
(resultSetType)
int TYPE_FORWARD_ONLY=1003;
int TYPE_SCROLL_INSENSITIVE=1004;
int TYPE_SCROLL_SENSITIVE=1005;
(resultSetConcurrency)
int CONCUR_READ_ONLY=1007;
int CONCUR_UPDATABLE=1008; //注意这里的UPDAT没有E
prepareStatement()和prepareCall()这两个方法都有一个String参数,该参数包含要执行的SQL语句。这个SQL语句(字符串形式)可以包含一个或者多个“?”用于标明参数的占位符,当多次执行一个查询而每次条件不同时,这种方式就非常有用。prepareCall()方法除了能够用于执行已存在于数据库中的存储过程以外,prepareCall()方法类似于prepareStatement()方法。createStatement()方法可以不带参数返回一个Statement对象。Statement对象中最为常用和有用的方法有:
ResuletSet executeQuery(String sql) throws SQLException
void executeUpdate(String sql) throws SQLExcepion
第一个方法返回一个结果集(ResultSet)对象,包含查询到的结果,第二个用于执行不返回任何结果的sql语句。
◎ResultSet对象包含叫做‘cursor’的游标,依靠游标,你可以操纵结果集中的特定行。游标的最初位置是在第一行之前,可以用ResultSet对象中的next()方法使游标前进到下一行位置。如果存在有效行,那么每次调用next()方法的返回值为true,如果在最后一行的位置调用next()方法则返回false。
4.实例分析:
这里使用最为常见的Access数据库。
步骤一、打开Access,创建一个新的数据库“db1.mdb”并将它保存在C://JavaApp路径下。然后在数据库中创建名为“usertable”的表。表中包含以下字段:ID(整型),Name(文本),Birthday(日期),Hobby(备注)。然后打开表任意输入3条以上记录。
步骤二、进入控制面板,进入管理工具文件夹,打开数据源(ODBC),在用户DSN处选择新增,在弹出来的窗口选择“Microsoft Access Driver(*.mdb)”后按完成,此时再弹出一个窗口,用来设置在应用程序中引用数据库的名称和数据库路径。在此窗口的数据源名处输入“user”,(你也可以自己定义),接着在数据库处按“选择”按钮,选择我们刚刚创建的数据库。按确定后即完成。这样我们就可以在Java应用程序中通过JDBC-ODBC桥来访问这个Access数据库。
示例代码如下:
package Examples;
import java.sql.*; //这里记入要导入这个包
public class ConnectDemo{
public static void main(String[] args){
Connection conn; //建立一个Connection对象
Statement stmt; //建立一个语句对象
ResultSet rs; //建立一个结果集对象
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); //检测JDBC驱动程序
conn=DriverManager.getConnection("jdbc:odbc:user"); //建立与数据库的连接
stmt= conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,ResultSet.CONCUR_READ_ONLY); // 建立语句对象,且是只能向前滚动,不能修改的。
// 如果执行 stmt.executeUpdate("update usertable set Name='mary' where ID=2");则会出错。
rs=stmt.executeQuery("Select * from usertable"); // 执行查询并返回结果集
while(rs.next()){
System.out.println(rs.getInt(1)+ " "+rs.getString(2)+" "+rs.getDate(3)+" "+rs.getString(4)); // 打印出表中的内容,对应表中不同字段我们使用不同的get方法。
// get方法中的数值表示第几个字段。注意ResultSet中的字段从1开始
}
// 如果这里再调用 rs.first()则会出现错误,因为结果集被声明只能向前滚动的
}catch(ClassNotFoundException e){
System.out.println("找不到JDBC驱动程序!");
e.printStackTrace();
}catch(SQLException e){
System.out.println("数据库路径错误或操作出错!");
e.printStackTrace();
}
}
}