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/test?
serverTimezone=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
需要查询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();
}
}
}
}
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();
}
}
}
}