JDBC编程
JDBC即java数据库互连,是
java
语言和数据库之间独立于数据库的连接标准
API
,
JDBC
从根本上来说是 一种规范,具体的实现需要依赖于具体数据库生产商提供jar
包【驱动】,提供了统一的接口用于访问不 同的底层数据库,允许使用java
语言编写不同的应用程序以访问数据库。
①为Java
语言定义了一个
SQL
调用级别的统一界面
②为访问关系型数据库提供了一个标准的界面
③所谓的JDBC
实际上就是一种用于执行
SQL
语句的
API,可以采用一致的方式连接不同的数据库系统,从而使用标准的SQL语言来存取数据库中的数据。
具体的数据库访问采用的都是
c/s
架构:
①支持多种不同的数据库服务器
②主要的业务逻辑集中在客户端中
③服务器端的逻辑侧重于数据库的操作
④胖客户端将频繁访问远程数据库,可能会导致网络流量增大问题
JDBC
的体系结构:
Java应用程序可以通过
Java API
与数据库连接,
JavaAPI
中的一组用
Java
语言编写的类和接口位于
java.sql 和javax.sql
包中,实际动作则是由
JDBC
驱动管理器通过数据库生产厂商提供的
JDBC
驱动程序与数据库管理系统进行连接
每个
JDBC
应用程序至少需要有一个
JDBC
驱动程序,
JDBC
驱动是
Driver
接口的实现类
①Driver接口是驱动程序需要实现的接口,
Driver
使
DriverManager
和
JDBC
应用可以独立于具体的数据库系统
② 在不同类型的应用中添加驱动的方式不同
将驱动程序拷贝到新建的文件夹中,然后使用右键将jar包添加到构建路径中
JDBC API
java.sql.DriverManager负责加载、拆除驱动程序,负责获取和数据库管理系统的连接
java.sql.Connection实现对某个数据库系统的连接 一个数据库管理系统能够提供的连接数是有限的,必须保证连接及时关闭
java.sql.Statement用于实现向数据库系统提交SQL语句 ,java.sql.PreparedStatement用于执行预编译的SQL语句 ,java.sql.CallableStatement用于提交执行存储过程 ,java.sql.ResultSet是数据库系统返回的查询结果集
JDBC
基本操作步骤:
加载驱动程序
创建数据库连接,必须保证及时关闭
提交执行SQL
语句
接收并处理SQL
的执行结果
关闭释放资源
1
、加载驱动
首先将驱动jar
包从数据库系统官方网站上下载下来,并将驱动
jar
包添加到构建路径中
Class.forName("驱动串
")
。这里的驱动串就是需要加载的
JDBC
驱动程序的名称
早期没有很多数据库提供驱动,所以
java
提供了通过微软的
ODBC
连接数据库的方法,这个驱动已经包 含在java
中,叫做
jdbc-odbc
桥接方式。例如访问
micorosoft office
中的
access
数据库的方法为
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver")
;
JDBC的驱动方式可以分为4种类型:JDBC-ODBC桥接方式、Native-API驱动、JDBC-Net驱动和Native-protocol驱动
//受检型异常
ClassNotFoundException Class.forName("com.mysql.cj.jdbc.Driver");
//从反射机制的角度上说new A()等价于Class.forName("com.yan.A").newInstance(),所以加 载操作也可以简化
new Driver();
如果使用JDBC高版本驱动时实际上还可以省略加载步骤
2
、获取连接
可以通过驱动管理器DriverManager
类获取和数据库系统的连接
Connection conn=DriverManager.getConnection("连接串","连接数据库的用户名称","对应的 口令");
连接串用于代表需要连接的数据库,连接串的标准 jdbc
主协议
:
子协议
:
其它部分
,但是不同的数据库系统其对应的连接串不同。例如连接oracle
则驱动串为
oracle.jdbc.OracleDriver
,连接串
为
jdbc:oracle:thin:@localhost:1521:test
// 受检型异常 ClassNotFoundException
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testserverTimezone=UTC","root","123456");
System.out.println(conn); //com.mysql.cj.jdbc.ConnectionImpl@365185bd
注意:数据库连接属于稀有资源,所以需要使用时进行创建,使用完毕必须结束关闭,不能依赖于垃圾回收。建议使用try/finally
结构
3
、构建语句对象
在与特定数据库建立连接后,就可以发送SQL
语句,在发送
SQL
语句之前需要创建一个语句对象最古老的方式是使用Statement
对象
Statement stmt=conn.createStatement();
ResultSet res=stmt.executeQuery("select * from tb_student");
一般不建议使用
Statement
对象,这个对象用于提交静态
sql
语句。有
sql注入漏洞,建议使用Statement 的子接口PreparedStatement
Statement对象中提供了
executeQuery
方法来执行查询操作,这个方法会返回查询结果集
ResultSet
类对象,其中包含
SQL
语句的查询结果
Statement对象中提供了
executeUpdate
方法来执行修改操作,这个方法会返回一个
int
值,表示 sql的增删改操作所影响的数据行数
在
test
数据库中有一个表
tb_student
mysql> select * from tb_student;
+----+--------+------+------+--------+
| id | name | age | sex | dept |
+----+--------+------+------+--------+
| 1 | 小黄 | 18 | 1 | 软工 |
| 2 | 小绿 | 16 | 0 | 计科 |
| 3 | 小紫 | 19 | 1 | 大数据 |
| 4 | 小蓝 | 16 | 1 | 软工 |
| 5 | 小橙 | 16 | 1 | 软工 |
| 6 | 小红 | 16 | 1 | NULL |
| 8 | 小白 | 16 | 0 | NULL |
+----+--------+------+------+--------+
7 rows in set (0.00 sec)
需要查询
tb_student
表
//注意导入包时不要出现错误
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Test1 {
public static void main(String[] args) throws Exception { // 受检型异常
ClassNotFoundException Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test? serverTimezone=UTC", "root","123456");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from tb_student");
}
}
4
、接收查询结果集
JDBC中使用
ResultSet
对象来表示查询结果集,可以理解为一个指向满足查询结果的行指针,其中并不存 放实际数据,所以在使用结果集之前不能关闭连接
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from tb_student");
5
、遍历处理结果集
注意:连接不能关闭
ResultSet
对象包含了执行查询后满足条件的所有行,提供了对应的访问方法,有一组对应的
getXxx
方法 获取指定列的值
while(rs.next()){ //用于移动行指针,同时判断是否有数据,如果有数据则返回为true,否则 false
/** | tb_student | CREATE TABLE `tb_student` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`age` int(11) DEFAULT '16',
`sex` tinyint(1) DEFAULT '1',
`dept` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 | */
//由于历史原因,列序号从1开始
long id=rs.getLong(1);//指定列时可以使用序号,也可以使用列名称,一般建议使用列名 称,因为数据表的结构会有变动
String name=rs.getString("name");
int age=rs.getInt("age");
boolean sex=rs.getBoolean("sex");
System.out.println(id+":"+name+":"+age+":"+sex);
}
一般列是什么数据类,则应该使用对应类型的getXxx
方法,实际上使用
getString
可以获取任意类型的列中的数据
如果执行修改操作,则返回的是
int
类型数据,表示受影响行数
Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql:///test? serverTimezone=UTC", "root", "123456");
Statement stmt = conn.createStatement();
int len=stmt.executeUpdate("update tb_student set dept='材料系' where id=8");
if(len>0)
System.out.println("修改成功!");
else
System.out.println("修改失败!");
6
、关闭对象
手动关闭ResultSet
、
Statement
和
Connection
,注意这里必须保证
Connection
对象关闭
建议使用
try/finally
结构
正向打开对象,逆向关闭对象
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Test3 {
public static void main(String[] args) {
Connection conn = null; Statement stmt = null; ResultSet rs = null;
String sql="select * from tb_student";
try {
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql:///test? serverTimezone=UTC", "root", "123456"); stmt = conn.createStatement();
rs=stmt.executeQuery(sql);
while(rs.next()){
long id=rs.getLong("id");
String name=rs.getString("name");
boolean sex=rs.getBoolean("sex");
System.out.println(id+"\t"+name+"\t"+(sex?"男":"女"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
} catch (SQLException e2) {
e2.printStackTrace();
}try {
if (stmt != null)
stmt.close();
} catch (SQLException e1) {
e1.printStackTrace();
}try {
if (conn != null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}