JDBC编程的步骤(一)

版权声明:本文为博主原创,未经同意不得转载 https://blog.csdn.net/weixin_42950079/article/details/86706989

提醒:编写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();

    }
}

控制台输出结果:
CD4356


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();

    }
}

控制台输出结果:
CD4356
OK,这样看起来代码是不是干净了很多

问题又来了
看了辅助类DBConnection的代码后,发现,为什么关闭ResultSet,Statement 和Connection资源的操作要分开放在各自的方法中,不能放在同一个方法中?
因为这是要考虑到执行增,删,改操作时,不会返回ResultSet结果集对象,所以在执行增,删,改操作的方法中不用关闭ResultSet资源,所以将关闭ResultSet,Statement 和Connection资源的操作要分开放在各自的方法中

猜你喜欢

转载自blog.csdn.net/weixin_42950079/article/details/86706989