JDBC编程第一篇 -- JDBC编程的基本步骤
提醒:编写JDBC程序前记得启动数据库服务器,并导入JDBC驱动jar包
JDBC编程6步曲:
第1步:注册mysql数据库驱动
第2步:通过DriverManager类获取数据库连接
第3步:通过Connection对象获取Statement对象
第4步:使用Statement执行SQL语句,返回一个ResultSet结果集对象
第5步:使用操作ResultSet结果集
第6步:关闭连接,释放资源
下面让我们来编写一个JDBC程序:
先创建数据库studentMS
和 数据库表student
,并插入三条记录
create database studentMS default character set utf8;
use studentMS
create table student (
id int(25) primary key,
name varchar (255) not null,
age int (25) not null,
specialty varchar (255) not null
);
insert into student values(170701,'张三',18,'中医学');
insert into student values(170702,'李四',20,'计算机');
insert into student values(170703,'王五',21,'社会学');
程序代码:
import java.sql.*;
public class JDBC {
//根据学号获取学生信息
public static void getStudentById(String id){
String driverClass="com.mysql.cj.jdbc.Driver";
String Url="jdbc:mysql://localhost:3306/studentMS?serverTimezone=GMT%2B8";
String username="root";
String userpass="root";
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try{
// 1.注册mysql数据库驱动
Class.forName(driverClass);
// 2.通过DriverManager类获取数据库连接
conn= DriverManager.getConnection(Url,username,userpass);
// 3.通过Connection对象获取Statement对象
stmt=conn.createStatement();
// 4.使用Statement执行SQL语句,返回一个ResultSet结果集
String sql="select*from student where id="+id;
rs=stmt.executeQuery(sql);
// 5.操作ResultSet结果集
System.out.println("学号"+" | "+"姓名"+" | "+"年龄"+" | "+"专业");
if(rs.next()){
//通过数据库表的列名来指定字段的值(当然也可以通过字段号来指定)
System.out.print(rs.getInt("id")+" | ");
System.out.print(rs.getString("name")+" | ");
System.out.print(rs.getInt("age")+" | ");
System.out.println(rs.getString("specialty"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭数据库连接,释放资源(数据库资源很宝贵,所以别忘了这一步了)
try {
if (rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(conn!=null||!conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//查询所有学生信息
public static void getAllStudent(){
String driverClass="com.mysql.cj.jdbc.Driver";
String Url="jdbc:mysql://localhost:3306/studentMS?serverTimezone=GMT%2B8";
String username="root";
String userpass="root";
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try{
// 1.注册数据库驱动
Class.forName(driverClass);
// 2.通过DriverManager类获取数据库连接
conn= DriverManager.getConnection(Url,username,userpass);
// 3.通过Connection对象获取Statement对象
stmt=conn.createStatement();
// 4.使用Statement执行SQL语句,返回一个ResultSet结果集
String sql="select*from student order by id";
rs=stmt.executeQuery(sql);
// 5.操作ResultSet结果集
System.out.println("学号"+" | "+"姓名"+" | "+"年龄"+" | "+"专业");
while(rs.next()){
//通过数据库表的列名来指定字段的值(当然也可以通过字段号来指定)
System.out.print(rs.getInt("id")+" | ");
System.out.print(rs.getString("name")+" | ");
System.out.print(rs.getInt("age")+" | ");
System.out.println(rs.getString("specialty"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭数据库连接,释放资源(数据库资源很宝贵,所以别忘了这一步了)
try {
if (rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(conn!=null||!conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
建一个测试类TestJDBC来测试一下
public class TestJDBC {
public static void main(String[] args) {
System.out.println("查询个人的信息:");
getStudentById("170701");
System.out.println("\n查询所以人的信息:");
getAllStudent();
}
}
控制台输出结果:
OK,完成一个JDBC程序后,我们来了解一下每一步的作用及注意事项
第1步:注册mysql数据库驱动
String driverClass="com.mysql.cj.jdbc.Driver";
Class.forName(driverClass);
com.mysql.cj.jdbc.Driver
是mysql驱动类
注意:
在注册JDBC驱动前记得现导入驱动jar包,
如果使用新版mysql驱动jar包,须使用com.mysql.cj.jdbc.Driver驱动类进行注册,
不要用com.mysql.jdbc.Driver驱动类注册
第2步:通过DriverManager类获取数据库连接
String Url="jdbc:mysql://localhost:3306/studentMS"+"?serverTimezone=GMT%2B8";
String username="root";
String userpass="root";
Connection conn = DriverManager.getConnection(Url,username,userpass);
jdbc:mysql
指定jdbc连接的数据库类型,这里指定的是mysql数据库
localhost
是本地主机名,如果连接的数据库在其他电脑上,则将localhost改为那个电脑的IP
3306
是服务器端口号,mysql默认端口号为3306
studentMS
是连接的数据库的名称
serverTimezone=GMT%2B8
表示将mysql服务器的时区设置为东八区(中国)的时区
username
是数据库用户名
userpass
是数据库用户密码
注意:
如果使用新版mysql驱动jar包,须将mysql服务器时区(serverTimezone)设置为当前系统的时区(GMT%2B8),
GMT%2B8代表东八区,mysql服务器默认为美国时区
如果是旧版的mysql驱动jar包,则无需设置时区
第3步:通过Connection对象获取Statement对象
Statement stmt=conn.createStatement();
第4步:使用Statement执行SQL语句,返回一个ResultSet结果集对象
String sql="select*from student where id="+id;
ResultSet rs=stmt.executeQuery(sql);
Statement接口有三种执行SQL语句的方法
- 分别为:
executeQuery()
,executeUpdate()
,execute()
执行查询语句时,一般用executeQuery()方法,该方法执行成功后,会返回一个ResultSet结果集对象。
执行增,删,改语句时,使用executeUpdate()方法,因为增,删,改操作不需要返回结果集对象, 只需返回更改的记录数,比如:增加记录的个数(行数),删除记录的个数,修改记录的个数
execute()方法可以用来执行任何SQL语句,
但执行查询语句时,不会返回结果集,而是返回true
执行增,删,改语句时,也不会返回更改的记录数,而是返回false
所以execute()方法一般在不清楚执行的是查询,还是增,删,改语句时才使用,即在动态执行SQL语句的方法中使用execute()方法
第5步:使用操作ResultSet结果集
//遍历结果集
while(rs.next()){
//通过数据库表的列名来指定字段的值(当然也可以通过字段号来指定)
System.out.print(rs.getInt("id")+" | ");
System.out.print(rs.getString("name")+" | ");
System.out.print(rs.getInt("age")+" | ");
System.out.println(rs.getString("specialty"));
}
不知道你们在刚接触JDBC的时候有没有这种疑惑?
为什么获取结果集的数据前,要先调用next()方法,next()有什么作用,难道不能直接获取结果集中的数据?
为什么上面代码中的while循环去掉,直接获取结果集中的数据会报错!!
在idea中用鼠标选中ResultSet对象,然后按ctrl+shift+B快捷键,查看ResultSet接口的源码后,
你会发现
ResultSet有游标的概念,刚开始时,游标指向结果集的第一行之前,
所以如果结果集的数据的行数>=1,那么调用next()方法首先会将游标移动到结果集的第一行,
第二次调用游标就会移动到结果集的第二行,以此类推,每一次调用next()方法,都会将结果集向下一行移动,直至游标位于结果集最后一行之后,就会返回false退出while循环
如果结果集中一行数据都没有,则直接返回false
所以,获取结果集的数据前,要先调用next()方法,将游标移动到结果集的第一行
从结果集中取出各列的值时,使用getXXX(列名/列号)
方法,xxx为当前列的数据类型,即你所操作数据库表中字段的数据类型。
getString() 取字符串型字段的值
getInt() 取整型字段的值
getDouble() 取double型字段的值
getBoolean() 取布尔型字段的值
getDate() 取日期型字段的值
比如上面代码中的id字段为int类型的字段,所以获取id字段值的方法为:rs.getInt("id")
或者 rs.getInt(1)
,id字段所在列号为1
第6步:关闭连接,释放资源
finally {
// 6.关闭数据库连接,释放资源(数据库资源很宝贵,所以别忘了这一步了)
try {
if (rs!=null){
rs.close();
}
if(stmt!=null){
stmt.close();
}
if(conn!=null||!conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
数据库资源很宝贵,数据库允许的并发访问连接数量有限,所以当操作数据库结束后,一定要记得关闭数据库连接,释放资源。
为了保证资源的释放,释放资源的操作建议放在finall代码块中。
第一个JDBC程序实现了,并且也讲解了每一步的注意事项,但不知道你们有没有发现上面的代码,每一个方法中都要配置连接数据库,完成连接数据库,释放资源的操作,并且这些操作在每个方法中都是一样的,而在做项目的时候可能还会定义,增,改,删等其它方法,如果每个方法中都有一大推这种一样的代码,这样代码看起来就会很乱,可读性差。
所以我们在做项目的时候,一般都会将数据库连接,关闭数据库连接,释放ResultSet和Statement资源的操作拿出来放到一个辅助类的方法中,这样在需要连接数据库,释放资源时,就直接调用辅助类中相应的方法即可
还是直接上代码吧,代码才是检验真理的唯一标准
辅助类DBConnection
import java.sql.*;
public class DBConnection {
private static final String driverClass="com.mysql.cj.jdbc.Driver";
private static final String Url="jdbc:mysql://localhost:3306/studentMS?serverTimezone=GMT%2B8";
private static final String username="root";
private static final String userpass="root";
/**
* 建立连接
* @return
*/
public static Connection getConnection(){
Connection conn=null;
try {
Class.forName(driverClass);
conn= DriverManager.getConnection(Url,username,userpass);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return conn;
}
/**
* 关闭连接
*/
public static void closeConnection(Connection conn){
try{
if(conn!=null||!conn.isClosed()){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭Statement
*/
public static void closeStatement(Statement stmt){
try{
if(stmt!=null){
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 关闭Statement
*/
public static void closeResultSet(ResultSet rs){
try{
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
数据库操作
import java.sql.*;
public class JDBC {
//根据学号获取学生信息
public static void getStudentById(String id){
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try{
// 1,2注册数据库驱动,并连接数据库
conn=DBConnection.getConnection();
// 3.通过Connection对象获取Statement对象
stmt=conn.createStatement();
// 4.使用Statement执行SQL语句,返回一个ResultSet结果集
String selectSQL="select*from student where id="+id;
rs=stmt.executeQuery(selectSQL);
// 5.操作ResultSet结果集
System.out.println("学号"+" | "+"姓名"+" | "+"年龄"+" | "+"专业");
while(rs.next()){
//通过数据库表的列名来指定字段的值(当然也可以通过字段号来指定)
System.out.print(rs.getInt("id")+" | ");
System.out.print(rs.getString("name")+" | ");
System.out.print(rs.getInt("age")+" | ");
System.out.println(rs.getString("specialty"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭数据库连接,释放资源
DBConnection.closeResultSet(rs);
DBConnection.closeStatement(stmt);
DBConnection.closeConnection(conn);
}
}
// 查询所有学生信息
public static void getAllStudent(){
Connection conn=null;
Statement stmt=null;
ResultSet rs=null;
try{
// 1,2注册数据库驱动,并连接数据库
conn=DBConnection.getConnection();
// 3.通过Connection对象获取Statement对象
stmt=conn.createStatement();
// 4.使用Statement执行SQL语句,返回一个ResultSet结果集
String selectSQL="select*from student order by id";
rs=stmt.executeQuery(selectSQL);
// 5.操作ResultSet结果集
System.out.println("学号"+" | "+"姓名"+" | "+"年龄"+" | "+"专业");
while(rs.next()){
//通过数据库表的列名来指定字段的值(当然也可以通过字段号来指定)
System.out.print(rs.getInt("id")+" | ");
System.out.print(rs.getString("name")+" | ");
System.out.print(rs.getInt("age")+" | ");
System.out.println(rs.getString("specialty"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6.关闭数据库连接,释放资源
DBConnection.closeResultSet(rs);
DBConnection.closeStatement(stmt);
DBConnection.closeConnection(conn);
}
}
}
测试类
public class TestJDBC {
public static void main(String[] args) {
System.out.println("查询个人的信息:");
getStudentById("170701");
System.out.println("\n查询所以人的信息:");
getAllStudent();
}
}
控制台输出结果:
OK,这样看起来代码是不是干净了很多
问题又来了
看了辅助类DBConnection的代码后,发现,为什么关闭ResultSet,Statement 和Connection资源的操作要分开放在各自的方法中,不能放在同一个方法中?
因为这是要考虑到执行增,删,改操作时,不会返回ResultSet结果集对象,所以在执行增,删,改操作的方法中不用关闭ResultSet资源,所以将关闭ResultSet,Statement 和Connection资源的操作要分开放在各自的方法中