1,什么是JDBC?
- JDBC是Java语言访问数据库的一种规范,是一套API
- JDBC (Java Database Connectivity) API,即Java数据库编程接口,是一组标准的Java语言中的接口和类,使用这些接口和类,Java客户端程序可以访问各种不同类型的数据库。(说白了就是用Java语言来操作数据库。原来我们操作数据库是在控制台使用SQL语句来操作数据库,JDBC是用Java语言向数据库发送SQL语句。)
2,JDBC的原理
JDBC规范采用接口和实现分离的思想设计了Java数据库编程的框架。接口包含在java.sql及javax.sql包中,其中java.sql属于JavaSE,javax.sql属于JavaEE。这些接口的实现类叫做数据库驱动程序,由数据库的厂商或其它的厂商或个人提供。
为了使客户端程序独立于特定的数据库驱动程序,JDBC规范建议开发者使用基于接口的编程方式,即尽量使应用仅依赖java.sql及javax.sql中的接口和类。
(早期SUN公司的天才们想编写一套可以连接天下所有数据库的API,但是当他们刚刚开始时就发现这是不可完成的任务,因为各个厂商的数据库服务器差异太大了。后来SUN开始与数据库厂商们讨论,最终得出的结论是,由SUN提供一套访问数据库的规范(就是一组接口),并提供连接数据库的协议标准,然后各个数据库厂商会遵循SUN的规范提供一套访问自己公司的数据库服务器的API出现。SUN提供的规范命名为JDBC,而各个厂商提供的,遵循了JDBC规范的,可以访问自己数据库的API被称之为驱动
JDBC是接口,而JDBC驱动才是接口的实现,没有驱动无法完成数据库连接!每个数据库厂商都有自己的驱动,用来连接自己公司的数据库。)
3,什么是JDBC驱动程序?
是各个数据库厂家根据JDBC的规范制作的JDBC实现类
4,JDBC驱动程序的四种类型
- 第一种类型的驱动程序的实现:是通过将JDBC的调用全部委托给其它编程接口来实现的,比如ODBC。这种类型的驱动程序需要安装本地代码库,即依赖于本地的程序,所以便携性较差。比如JDBC-ODBC桥驱动程序
【ODBC(Open Database Connectivity)是一组对数据库访问的标准API,这些API通过SQL来完成大部分任务,而且它本身也支持SQL语言,支持用户发来的SQL。ODBC定义了访问数据库API的一组规范,这些API独立于形色各异的DBMS和编程语言。也就是说,一个基于ODBC的应用程序,对数据库的操作不依赖任何DBMS,不直接与DBMS打交道,所有的数据库操作由对应的DBMS的ODBC驱动程序完成。不论是SQL Server、Access还是Oracle数据库,均可用ODBC API进行访问。
由此可见,ODBC的最大优点是能以统一的方式处理所有的数据库。】
【 jdbc-odbc桥:由于ODBC被广泛地使用,为了让JDBC能够访问几乎所有的数据库,产生了JDBC-ODBC桥。JDBC-ODBC桥是一个JDBC驱动程序,它通过将JDBC操作转换为ODBC操作来实现JDBC操作。它仍然是一种适配模式。
目前大部分厂商都实现了jdbc接口,jdbc-odbc桥就退出了历史舞台。】 - 第二种类型的驱动程序的实现是:部分基于Java语言的。即该驱动程序一部分是用Java语言编写,其它部分委托本地的数据库的客户端代码来实现。同类型1的驱动一样,该类型的驱动程序也依赖本地的程序,所以便携性较差
- 第三种类型的驱动程序的实现是:全部基于JAVA语言的。该类型的驱动程序通常由某个中间件服务器提供,这样客户端程序可以使用数据库无关的协议和中间件服务器进行通信,中间件服务器再将客户端的JDBC调用转发给数据库进行处理
- 第四种类型的驱动程序的实现是:全部基于JAVA语言的。该类型的驱动程序中包含了特定数据库的访问协议,使得客户端可以直接和数据库进行通信
5,JDBC类结构
5.1 DriverManger
5.1.1 DriverManager是什么
DriverManager是管理一组 JDBC 驱动程序的基本服务。这个是一个实现类,它是一个工厂类,用来生产Driver对象的。这个类的结构设计模式为工厂方法, 事实上,一般我们操作Driver,获取Connection对象都是交给DriverManager统一管理的。DriverManger可以注册和删除加载的驱动程序,可以根据给定的url获取符合url协议的驱动Driver或者是建立Conenction连接,进行数据库交互
以下是DriverManager的关键方法摘要:
Q: DriverManager 内部持有这些注册进来的驱动 Driver,由于这些驱动都是 java.sql.Driver
类型,那么怎样才能获得指定厂商的驱动Driver呢?
A:java.sql.Driver接口规定了厂商实现该接口,并且定义自己的URL协议。厂商们实现的Driver接口通过acceptsURL(String
url)来判断此url是否符合自己的协议,如果符合自己的协议,则可以使用本驱动进行数据库连接操作,查询驱动程序是否认为它可以打开到给定
URL 的连接。
5.1.2 DriverManager的作用
DriverManager 类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager 类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。
对于简单的应用程序,一般只需要DriverManager.getConnection(该方法将建立与数据库的连接)方法即可。JDBC 允许用户调用 DriverManager 的方法 getDriver、getDrivers 和 registerDriver 及 Driver 的方法 connect。但多数情况下,让 DriverManager 类管理建立连接的细节为上策。
这里所谓的驱动,其实就是实现了java.sql.Driver接口的类。如oracle的驱动类是 oracle.jdbc.driver.OracleDriver.class(此类可以在oracle提供的JDBC jar包中找到),此类实现了java.sql.Driver接口。
由于驱动本质上还是一个class,将驱动加载到内存和加载普通的class原理是一样的:使用Class.forName(“driverName”)。以下是将常用的数据库驱动加载到内存中的代码:
// 加载Oracle数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
// 加载MySQL数据库驱动
Class.forName("com.mysql.jdbc.Driver");
注意:Class.forName()将对应的驱动类加载到内存中,然后执行内存中的static静态代码段,代码段中,会创建一个驱动Driver的实例,放入DriverManager中,供DriverManager使用。
例如,在使用Class.forName() 加载oracle的驱动oracle.jdbc.driver.OracleDriver时,会执行OracleDriver中的静态代码段,创建一个OracleDriver实例,然后调用DriverManager.registerDriver()注册:
static {
Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");
try {
if (defaultDriver == null) {
//创建一个OracleDriver实例,然后注册到DriverManager中
defaultDriver = new OracleDriver();
DriverManager.registerDriver(defaultDriver);
}
} catch (RuntimeException localRuntimeException) {
} catch (SQLException localSQLException){
}
5.1.3 使用DriverManager获取指定Driver
对于驱动加载后,如何获取指定的驱动程序呢?这里,DriverManager的静态方法getDriver(String url)可以通过传递给的URL,返回可以打开此URL连接的Driver。
比如,我想获取oracle的数据库驱动,只需要传递形如jdbc:oracle:thin:@::或者jdbc:oracle:thin:@//:/ServiceName的参数给DriverManager.getDriver(String url) 即可:
Driver oracleDriver =DriverManager.getDriver("jdbc:oracle:thin:@<host>:<port>:<SID>");
实际上,DriverManager.getDriver(String url)方法是根据传递过来的URL,遍历它维护的驱动Driver,依次调用驱动的Driver的acceptsURL(url),如果返回acceptsURL(url)返回true,则返回对应的Driver
package cn.tedu.pojo;
import java.sql.SQLException;
public class Hello {
public static Driver getDriver(String paramString) throws SQLException {
//省略部分代码。。。。
Iterator localIterator = registeredDrivers.iterator();
//遍历注册的驱动
while (localIterator.hasNext()) {
DriverInfo localDriverInfo = (DriverInfo) localIterator.next();
if (isDriverAllowed(localDriverInfo.driver, localClass))
try {
//如果accepsURL() 为true,返回对应的driver
if (localDriverInfo.driver.acceptsURL(paramString)) {
//返回对应的driver
return localDriverInfo.driver;
}
} catch (SQLException localSQLException) {
}
else
println(" skipping: " + localDriverInfo.driver.getClass().getName());
}
throw new SQLException("No suitable driver", "08001");
//-----省略部分代码
}
5.2 Driver
5.2.1 Driver是什么
Java.sql.Driver 接口是所有 JDBC 驱动程序需要实现的接口。是驱动程序对象的接口,它指向一个实实在在的数据库驱动程序对象。DriverManager工厂中有个方法:getDriver(String URL),通过这个方法可以得到驱动程序对象,这个方法是在各个数据库厂商按JDBC规范设计的数据库驱动程序包里的类中静态实现的,也就是在静态块中
5.2.2 Driver的作用
这个接口是提供给数据库厂商使用的,不同数据库厂商提供不同的实现。在程序中不需要直接去访问实现了 Driver 接口的类,而是由驱动程序管理器类(java.sql.DriverManager)去调用这些Driver实现。
其中,acceptsURL(String url) 方法用来测试对指定的url,该驱动能否打开这个url连接。driver对自己能够连接的url会制定自己的协议,只有符合自己的协议形式的url才认为自己能够打开这个url,如果能够打开,返回true,反之,返回false;
public class Hello {
public boolean acceptsURL(String paramString) {
if (paramString.startsWith("jdbc:oracle:")) {
return (oracleDriverExtensionTypeFromURL(paramString) > -2);
}
return false;
}
private int oracleDriverExtensionTypeFromURL(String paramString) {
int i = paramString.indexOf(58) + 1;
if (i == 0) {
return -2;
}
int j = paramString.indexOf(58, i);
if (j == -1) {
return -2;
}
if (!(paramString.regionMatches(true, i, "oracle", 0, j - i))) {
return -2;
}
++j;
int k = paramString.indexOf(58, j);
if (k == -1) {
return -3;
}
String str = paramString.substring(j, k);
if (str.equals("thin")) {
return 0;
}
if ((str.equals("oci8")) || (str.equals("oci"))) {
return 2;
}
return -3;
}
}
由上可知oracle定义了自己应该接收什么类型的URL,自己能打开什么类型的URL连接(注意:这里acceptsURL(url)只会校验url是否符合协议,不会尝试连接判断url是否有效) 。
5.2.3 手动加载驱动 Driver 并实例化进行数据库操作的例子
public static void driverTest(){
try{
//1.加载oracle驱动类,并实例化
Driver driver=(Driver)Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
//2.判定指定的URL oracle驱动能否接受(符合oracle协议规则)
boolean flag=driver.acceptsURL("jdbc:oracle:thin:@127.0.0.1:1521:xe");
//标准协议测试
boolean standardFlag1=driver.acceptsURL("jdbc:oracle:thin:@//<host>:<port>/ServiceName");
boolean standardFlag2=driver.acceptsURL("jdbc:oracle:thin:@<host>:<port>:<SID>");
System.out.println("协议测试:"+flag+"\t"+standardFlag1+"\t"+standardFlag2);
//3.创建真实的数据库连接:
String url="jdbc:oracle:thin:@127.0.0.1:1521:xe";
Properties props=new Properties();
props.put("user","louluan");
props.put("password","123456");
Connection connection=driver.connect(url,props);
//connection 对象用于数据库交互,代码省略。。。。。
}catch(Exception e){
System.out.println("加载Oracle类失败!");
e.printStackTrace();
}finally{
}
上述的手动加载Driver并且获取连接的过程稍显笨拙:如果现在我们加载进来了多个驱动Driver,那么手动创建Driver实例,并根据URL进行创建连接就会显得代码杂乱无章,并且还容易出错,并且不方便管理。JDBC中提供了一个DriverManager角色,用来管理这些驱动Driver。
5.2.4 使用DriverManager注册和取消注册驱动Driver
当使用Class.forName(“driverName”)加载驱动的时候,会向DriverManager中注册一个Driver实例。以下代码将验证此说法:
> public static void defaultDriver(){
> try {
>
> String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
>
> //1.将Driver加载到内存中,然后执行其static静态代码,创建一个OracleDriver实例注册到DriverManager中
> Class.forName("oracle.jdbc.driver.OracleDriver");
> //取出对应的oracle 驱动Driver
> Driver driver = DriverManager.getDriver(url);
> System.out.println("加载类后,获取Driver对象:"+driver);
>
> //将driver从DriverManager中注销掉
> DriverManager.deregisterDriver(driver);
> //重新通过url从DriverManager中取Driver
> driver = DriverManager.getDriver(url);
> System.out.println(driver);
>
> } catch (Exception e) {
> System.out.println("加载Oracle类失败!");
> e.printStackTrace();
> } finally{
>
> }
> }
以上代码主要分以下几步:
- 首先是将 oracle.jdbc.driver.OracleDriver加载到内存中;
- 然后便调用DriverManager.getDriver()去取Driver实例;
- 将driver实例从DriverManager中注销掉;
- 尝试再取 对应url的Driver实例;
上述代码执行的结果如下:
从执行结果看,正好能够验证以上论述:当第四步再次获取对应url的 Driver 实例时,由于已经被注销掉了,找不到适当的驱动Driver,抛出了 “Not suitable driver” 的异常。
将上述的例子稍作变化,在注销掉了静态块创建的driver后,往DriverManager注册一个自己创建的Driver对象实例(具体步骤请看注释):
public static void defaultDriver(){
try {
String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
//1.将Driver加载到内存中,然后执行其static静态代码,创建一个OracleDriver实例注册到DriverManager中
Driver dd = (Driver)Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
//2.取出对应的oracle 驱动Driver
Driver driver = DriverManager.getDriver(url);
System.out.println("加载类后,获取Driver对象:"+driver);
//3. 将driver从DriverManager中注销掉
DriverManager.deregisterDriver(driver);
//4.此时DriverManager中已经没有了驱动Driver实例,将创建的dd注册到DriverManager中
DriverManager.registerDriver(dd);
//5.重新通过url从DriverManager中取Driver
driver = DriverManager.getDriver(url);
System.out.println("注销掉静态创建的Driver后,重新注册的Driver: "+driver);
System.out.println("driver和dd是否是同一对象:" +(driver==dd));
} catch (Exception e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} finally{
}
}
以下代码运行的结果:
以上代码先创建了一个Driver对象,在注销了DriverManager中由加载驱动过程中静态创建驱动之后,注册到系统中,现在DriverManager中对应url返回的Driver 即是在代码中创建的Driver对象。
5.2.5 使用DriverManager创建 Connection 连接对象
创建 Connection 连接对象,可以使用驱动Driver的 connect(url,props),DriverManager 提供的getConnection()方法,此方法通过url自动匹配对应的驱动Driver实例,然后调用对应的connect方法返回Connection对象实例。
Driver driver = DriverManager.getDriver(url);
Connection connection = driver.connect(url, props);
上述代码等价于:
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection(url, props)
5.2.6 jdbc.drivers
DriverManager 作为 Driver 的管理器,它在第一次被使用的过程中(即在代码中第一次用到的时候),它会被加载到内存中,然后执行其定义的static静态代码段,在静态代码段中,有一个 loadInitialDrivers() 静态方法,用于加载配置在jdbc.drivers 系统属性内的驱动Driver,配置在jdbc.drivers 中的驱动driver将会首先被加载:
static {
loadInitialDrivers();//加载配置在jdbc.drivers系统变量中的驱动driver
println("JDBC DriverManager initialized");
SET_LOG_PERMISSION = new SQLPermission("setLog");
}
private static void loadInitialDrivers() {
String str1;
try {
str1 = (String) AccessController
.doPrivileged(new PrivilegedAction() {
public String run() {
return System.getProperty("jdbc.drivers");//返回jdbc.drivers值
}
});
} catch (Exception localException1) {
str1 = null;
}
//省略部分代码......
if ((str1 == null) || (str1.equals("")))
return;
String[] arrayOfString1 = str1.split(":");
println("number of Drivers:" + arrayOfString1.length);
for (String str2 : arrayOfString1)
try {
//Class.forName加载对应的driver
Class.forName(str2, true, ClassLoader.getSystemClassLoader());
} catch (Exception localException2) {
println("DriverManager.Initialize: load failed: "
+ localException2);
}
}
以下是通过jdbc.drivers加载驱动driver的方式:
String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
//设置值系统变量jdbc.drivers
System.setProperty("jdbc.drivers", "oracle.jdbc.driver.OracleDriver");
//2.通过特定的url获取driver
Driver driver = DriverManager.getDriver(url);
//打印是否存在
System.out.println(driver);
一定要在第一次使用DriverManager之前设置jdbc.drivers,因为DriverManager中的static静态代码段只会被执行 一次!
5.3 Connection
5.3.1 什么是Connection
Connection表示与特定数据库的连接,可以获取到数据库的一些信息,这些信息包括:其表信息,应该支持的SQL语法,数据库内有什么存储过程,此链接功能的信息等等。
Q:这个接口可以指向一个数据库连接对象,那么如何得到这个连接对象呢?
A:是通过DriverManager工厂中的getConnection(String URL)方法得到的
5.3.2 Connection的作用
- 创建可以执行sql语句或者存储过程的对象statement,用来和数据库进行交互;
比如,以下代码创建了几种不同类型的Statement:
//加载Oracle数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//根据特定的URL,返回可以接受此URL的数据库驱动对象
Driver driver = DriverManager.getDriver(URL);
//使用数据库驱动创建数据库连接Connection会话
Connection connection = driver.connect(URL, props);
//创建静态的sql语句 Statement 对象来将 SQL 语句发送到数据库。
Statement staticStatement= connection.createStatement();
//创建CallableStatement 对象来调用数据库存储过程。
CallableStatement callableStatement = connection.prepareCall(sqlString);
//创建参数化的Statement对象
PreparedStatement preparedStatement = connection.prepareStatement(sqlString);
- 控制sql语句的事务;
Connection默认情况下,对于创建的statement执行的sql语句都是自动提交的,即在statement语句执行完后,自动执行commit操作,将结果影响到物理数据库。为了满足更好地事务控制需求,我们也可以手动地控制事务,手动地对statement 的sql语句执行进行提交(commit)或者回滚(rollback)。
下面通过一个简单的例子演示connection的事务控制:
String sqlString="insert into tableName(column1,column2) values(value1,value2)";
//加载Oracle数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//根据特定的URL,返回可以接受此URL的数据库驱动对象
Driver driver = DriverManager.getDriver(URL);
//使用数据库驱动创建数据库连接Connection会话
connection = driver.connect(URL, props);
//使用自定义的事务,要设置connection不自动提交
connection.setAutoCommit(false);
//创建静态的sql语句 Statement 对象来将 SQL 语句发送到数据库。
Statement staticStatement= connection.createStatement();
try{
//执行插入操作
staticStatement.execute(sqlString);
staticStatement.getConnection().commit();//和上面的connection等价,statement只有一个创建自身的connection的引用
}catch(Exception e)
{
//有异常,则rollback
staticStatement.getConnection().rollback();
}
- 获取数据库连接的元数据,即数据库的整体综合信息。
连接的数据库整体信息被封装在了一个 DatabaseMetaData类型的对象上,可以通过以下代码获得:
DatabaseMetaData databaseMetaData = connection.getMetaData();
5.4 Statement
5.4.1 什么是Statement
Statement用于执行静态的SQL语句的接口,通过Connection中的createStatement方法得到的
5.4.2 Statement的作用是什么
Statement 的功能在于根据传入的sql语句,将传入sql经过整理组合成数据库能够识别的sql语句(对于静态的sql语句,不需要整理组合;而对于预编译sql语句和批量语句,则需要整理),然后传递sql请求,之后会得到返回的结果。对于查询sql,结果会以ResultSet的形式返回。
SQL语句可以分为增删改查(CRUD,Create,Read,Update,Delete)四种形式,JDBC 从对数据更新与否的角度上看,将上面的四种形式分为两类:查询类别和更新类别。即:
-
查询类别:select 语句
-
更新类别:Insert 、update、delete语句
对应地,Statement执行sql的几种形式: -
对sql语句类型不进行区分,执行sql语句的方法
statement提供了execute(String sql)方法支持此种形式,定义如下:
-
如果是执行的sql是查询类型的select语句,此方法会返回true,需要自己再调用 statement.getResultSet()
方法来获取 Resultset结果集; -
如果是执行的更新类的sql语句如
update,delete,insert语句,此方法会返回false,自己调用statement.getUpdateCount()
返回sql语句影响的行数。
-
对查询类型的sql语句的执行方法
statement提供了executeQuery(String sql)方法支持此形式,定义如下:
-
对更新类的sql语句 的执行方法
statement提供了executeQuery(String sql)方法支持此形式,定义如下:
4.批量sql的执行方法
有时候需要将一些sql语句一起提交给数据库,批量执行,statement提供了一些方法,对批量sql的支持:
5.5 ResultSet
5.5.1 什么是ResultSet
ResultSet用于指向结果集对象的接口,结果集对象是通过Statement中的execute等方法得到的
5.5.2 ResultSet的作用
当Statement查询sql执行后,会得到ResultSet对象,ResultSet对象是sql语句查询的结果,作为数据库结果的映射,其映射关系如下图所示。
ResultSet对从数据库返回的结果进行了封装,使用迭代器的模式逐条取出结果集中的记录。其遍历结果集的基本形式如下:
while(resultSet.next())
{
// 传入列明或者列索引获取记录中对应列的值
resultSet.getXXX(param);
}
5.5.2.1 ResultSet游标的移动和定位
Resultset 提供了很多游标定位的方法,部分方法已经在下面列出:
5.5.2.2 ResultSet结果集的元数据信息
元信息是指关于 ResultSet 对象中列的类型和属性信息的对象。可以通过以下方法获取:
5.5.2.3 ResultSet.getXXX(param) 、ResultSet.updateXXX()的XXX问题
JDBC中定义了数据库中的数据类型和java数据类型的映射,用于数据库和Java数据类型之间的转换。在使用ResultSet去记录中的某一列值的时候,用户要根据数据库对应列的数据类型地应的java数据类型,否则的话有可能抛出异常。下图定义了数据库和Java类型之间的映射:
6,常用数据库的驱动程序及JDBC URL
6.1 Oracle数据库:
- 驱动程序包名:ojdbc14.jar
- 驱动类的名字:oracle.jdbc.driver.OracleDriver
- JDBC URL:jdbc:oracle:thin:@dbip:port:databasename
- 说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部分需要根据数据库的安装情况填写。其中各个部分含义如下: - dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
- port –为数据库的监听端口,需要看安装时的配置,缺省为1521。
- databasename –为数据库的SID,通常为全局数据库的名字。
举例如果要访问本地的数据库allandb,端口1521,那么URL写法如下:
jdbc:oracle:thin:@localhost:1521:allandb
下载地址如下: http://www.oracle.com/technology/software/tech/java/sqlj_jdbc/index.html
6.2 SQL Server数据库
- 驱动程序包名:msbase.jar mssqlserver.jar msutil.jar
- 驱动类的名字:com.microsoft.jdbc.sqlserver.SQLServerDriver
- JDBC URL:jdbc:microsoft:sqlserver://dbip:port;DatabaseName=databasename
- 说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下: - dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
- port –为数据库的监听端口,需要看安装时的配置,缺省为1433。
- databasename –数据库的名字。
举例如果要访问本地的数据库allandb,端口1433,那么URL写法如下:
jdbc: microsoft: sqlserver:@localhost:1433; DatabaseName =allandb
下载地址:http://www.microsoft.com/downloads/details.aspx
6.3 MySQL数据库
- 驱动程序包名:mysql-connector-java-3.1.11-bin.jar
- 驱动类的名字:com.mysql.jdbc.Driver
- JDBC URL:jdbc:mysql://dbip:port/databasename
- 说明:驱动程序包名有可能会变
JDBC URL中黑色字体部分必须原封不动的保留,为该驱动识别的URL格式。红色字体部需要根据数据库的安装情况填写。其中各个部分含义如下: - dbip –为数据库服务器的IP地址,如果是本地可写:localhost或127.0.0.1。
- port –为数据库的监听端口,需要看安装时的配置,缺省为3306。
- databasename –数据库的名字。
举例如果要访问本地的数据库allandb,端口1433,那么URL写法如下:
jdbc:mysql://localhost:3306/allandb
下载地址:http://dev.mysql.com/downloads/connector/j/
6.4 Access数据库
- 驱动程序包名:该驱动程序包含在JavaSE中,不需要额外安装。
- 驱动类的名字:sun.jdbc.odbc.JdbcOdbcDriver
- JDBC URL:jdbc:odbc:datasourcename
说明:该驱动只能工作在Windows系统中,首先需要在操作系统中建立一个可以访问Access数据库的本地数据源(ODBC),如果名字为allandb,那么URL写法如下:
jdbc:odbc:allandb
7,JDBC工作的基本流程
一个基本的JDBC工作流程,分为以下几步:
- 加载特定数据库驱动器实现类,并注册驱动器(Driver会注册到DriverManager中);
- 根据特定的URL,返回可以接受此URL的数据库驱动对象Driver;
- 使用数据库驱动 Driver 创建数据库连接Connection会话;
- 使用 Connection对象创建 用于操作sql的Statement对象;
- statement对象 .执行 sql语句,返回结果ResultSet 对象;
- 处理ResultSet中的结果;
- 关闭连接,释放资源
7.1 Test
public class DBConnection {
static final String URL = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
static final String USER_NAME ="louluan";
static final String PASSWORD = "123456";
public static void main(String[] args) {
connectionTest();
}
public static void connectionTest(){
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
//1.加载类,并注册驱动器(Driver会注册到DriverManager中)
//加载Oracle数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
//2.根据特定的URL,返回可以接受此URL的数据库驱动对象
Driver driver = DriverManager.getDriver(URL);
Properties props = new Properties();
props.put("user", USER_NAME);
props.put("password", PASSWORD);
//3.使用数据库驱动创建数据库连接Connection会话
connection = driver.connect(URL, props);
//4.获得Statement对象
statement = connection.createStatement();
//5.执行 sql语句,返回结果
resultSet = statement.executeQuery("select * from hr.employees");
//6.处理结果,取出数据
while(resultSet.next())
{
System.out.println(resultSet.getString(2));
}
//7.关闭链接,释放资源
} catch (ClassNotFoundException e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
//使用完成后管理链接,释放资源,释放顺序应该是: ResultSet ->Statement ->Connection
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
8,JDBC工作时序图
9,JDBC 操作练习
基于 JDBC 技术操作表中数据,并进行单元测试。
第一步:定义单元测试类,关键代码如下:
- 通过此单元测试类获取数据源对象,并且通过数据对象获取数据库连接
- @SpringBootTest 描述的类为Spring Boot中的单元测试类
- SpringBoot 中的单元测试类必须放在启动类的包或者子包中
- SpringBoot 中的单元测试类必须用@SpringBootTest注解描述
package com.cy.pj.sys.dao;
import org.junit.jupiter.api.Test; import javax.sql.DataSource; import java.sql.*;
@SpringBootTest
public class JdbcTests {//is a Object
@Autowired
private DataSource dataSource;//HikariDataSource (类) }
第二步:在单元测试类中添加向表中写入数据的第一种方法,关键代码如下:
@Test
void testSaveNotice01() throws SQLException {
//1.建立连接 (负责与数据库进行通讯)
Connection conn = dateSource.getConnection();
//2.创建 statement(sql 传送器->负责与将 sql 发送到数据库端)
String sql="insert into sys_notice " +
" (title,content,type,status, createdTime,createdUser,modifiedTime,modifiedUser) " +
" values ('加课通知','本周六加课','1','0', now(),'tony',now(),'tony') ";
//这种方式 Statement 的创建,适合 sql 中不需要动态传入值的方式。
Statement state = conn.createStatement();
//3.发送 sql
state.execute(sql);
//4.处理结果
//5.释放资源(后续释放资源要写到 finally 代码块中)
state.close();
conn.close();
}
在单元测试类中添加向表中写入数据的第二种方法
@Test
void testSaveNotice02() throws SQLException {
// 1.建立连接 (负责与数据库进行通讯)
Connection conn = dateSource.getConnection();
// 2.创建 statement(sql 传送器->负责与将 sql 发送到数据库端)
String sql="insert into sys_notice " +
" (title,content,type,status, createdTime,createdUser,modifiedTime,modifiedUser) " +
" values (?,?,?,?,?,?,?,?) ";
// 3.预编译方式创建 Statement 对象
PrepareStatement stmt = conn.prepareStatement();
// 4.为 sql 中的?号赋值
stmt.setString(1,"开学通知");
stmt.setString(2,"2021年3月18号 开学");
stmt.setString(3,"1"); stmt.setString(4,"0");
stmt.setTimestamp(5, new Timestamp(System.currentTimeMillis()));
stmt.setString(6,"jason");
stmt.setTimestamp(7, new Timestamp(System.currentTimeMillis()));
stmt.setString(8,"tony");
// 5.发送sql
stmt.execute();
// 6.处理结果
// 7.释放资源
conn.close();
stmt.close();
}