javaweb基础----JDBC(一)

发布时间:2024年01月09日

一、什么是JDBC

JDBC全称为Java数据库连接(Java Database Connectivity),是一套用于执行SQL语句的Java API。应用程序可以通过这套API连接到关系型数据库,并使用SQL语句完成对数据中数据的查询、增加、更新和删除等操作。

JDBC在应用程序与数据库之间起到了一个桥梁作用,当应用程序使用JDBC访问特定的数据库时,需要通过不同数据库驱动(所谓数据库驱动就是数据库厂商提供链接数据库的jar包)与不同数据库进行连接,连接后即可对该数据库进行相应的操作。

由于不同的数据库厂商提供的数据库驱动各不相同,在使用不同的数据库的时候需要学习对应的数据库驱动的api,对于开发人员来说学习成本会非常高.

于是sun公司提供了jdbc规范.本质上是一大推的接口,所有的数据库驱动都实现这一套接口,这样如果换数据库只需要换驱动包即可.

驱动包和jdbc规则的关系是父接口和实现类的关系.

JDBC常用API主要位于Java.sql包中,该包定义了一系列访问数据库的接口和类:

1.Driver 接口:代表驱动程序;

2.DriverManager 类:驱动程序管理员;

3.Connection 接口:代表数据库连接;

4.Statement 、PreparedStatement、CallableStatement 接口:代表数据库操作对象;

5.ResultSet 接口:代表结果集;

6.DatabaseMetadata、ResultSetMetadata接口:代表元数据;

7.Types 类:代表JDBC类型。??

二、JDBC入门代码

1 、在IDEA下新建工程并在工程目录下新建lib文件夹

2、 将数据库驱动拷贝到lib文件夹下

这是Java与数据库建立链接的前提基础。

然后现在来准备数据,构建一个数据库表:

前提条件准备完毕,开始在IDEA中写代码与数据库建立链接。

导入包。

public class Demo1 {                          //抛异常
    public static void main(String[] args) throws Exception {
        //1 注册驱动                  //报错1、抛异常2、或者try/catch捕获异常
        DriverManager.registerDriver(new Driver());
        //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb_21","root","*******");
        //3 获取执行sql语句的对象
        Statement stat = conn.createStatement();
        //4 执行sql语句并拿到结果
        //查询操作使用的方法只能是executeQuery
        ResultSet rs=stat.executeQuery("select * from user"); //ResultSet结果集/虚拟表
        //5 处理执行结果
        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));

        }
        //6 释放资源
        conn.close();
        stat.close();
        rs.close();
    }
}

异常的处理方法:1、直接抛异常,throws Exception? ? 2、用try / catch捕获处理异常

第一步(1)注册驱动? ? DriverManager.registerDriver(new Driver() );

用驱动包中的驱动程序管理员创建注册驱动Driver。

第二步(2)获取链接? ? Connection conn = DriverManager.getConnection(url:" jdbc:mysql://localhost:3306/mydb_21", user:" root ",password:" ******* ");

用驱动管理程序创建获取链接,getConnection方法有3个重载方法,上文的这个是包含3个string类型的方法,url:数据库地址,后面是 "协议 :?子协议 :// IP:端口号 / 数据库名称 "

user: 数据库用户名 ,password:密码。

重载方法2:

我们知道要链接到数据库需要数据库地址、数据库用户名和密码3样东西,无论如何都绕不开这些,这里2个参数保留了数据库地址参数,而将用户名密码封装在Properties中。

      //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Properties info = new Properties();
        info.setProperty("user","root");
        info.setProperty("password","*********");
        Connection conn=DriverManager.getConnection("",info);
创建一个Properties对象info,将用户名密码封装其中。

重载方法3:

如上所述,连接数据库绕不开三要素,这里只需要一个参数url,实际上是用? 和&符号将用户名密码连到数据库地址后面:

      //2 获取链接                                     //协议:子协议://IP:端口号3306/数据库名称
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb-21?user=root&password=*********");

类似网址中的:
CSDNicon-default.png?t=N7T8https://mp.csdn.net/mp_blog/creation/editor?spm=1011.2124.3001.6192

第三步(3)? 获取执行sql语句的对象

?Statement stat = conn.createStatement();

用上一步的conn对象创建stat对象,用于执行sql语句。

第四步(4)? 查询sql语句并拿到结果

ResultSet rs = stat.executeQuery("select* from user);

stat是用来执行sql语句select* from user的对象,将结果赋给rs变量,executeQuery方法是只能查询操作使用,返回值是ResultSet,还有一个方法是executeUpdate,返回值是int。

ResultSet是结果集/虚拟表。

?第五步(5)? 处理执行结果

        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }

?将执行结果(数据库数据)打印在终端上。

? rs.next() 是游标,数据库下一行有数据时返回true,否则返回false。

getObject()是获取数据,因为不知道数据库表中存的是什么类型的数据,Object是所有类的子类。

第六步(6)? 释放资源

conn.close();

stat.close();

rs.close();? ? ?顺序无所谓,哪个关闭都行。

一定要记得关闭释放资源,否则内存会不够。

上述流程可以形象地抽象为下面一张图:

左边是IDEA,可抽象为城市A,右边是与之建立链接的数据库,可抽象为城市B。

中间要想建立连接需要搭建桥梁Connection,也需要建桥的人DriverManager,开往B的车辆Statement返回时以ResultSet的形式返回。

三、各部分详解

(1)DriverManager.registerDriver(new Driver() );

?进入registerDriver方法的定义中,我们发现驱动被注册了2次,并且高度依赖驱动包。这是该语句的2个问题。

解决方法:使用驱动的加载。

Class.forName("com.mysql.jdbc.Driver"); 用该语句代替上面的注册驱动。

(2)stat执行sql语句

有executeQuery方法和executeUpdate方法,前者用于查询操作,后者用于增删改操作。

executeUpdate方法的返回值是int,以下是示例:

public class Demo2 {
    @Test                                      //抛异常
    public void test01() throws Exception {
        //1、加载驱动
        Class.forName("com.mysql.jdbc.Driver");
        Properties info = new Properties();
        info.getProperty("user", "root");
        info.getProperty("password", "********");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb-21");
        Statement stat = conn.createStatement();
        int i = stat.executeUpdate("insert into user values(5,'eee',29,'男')");
        if (i > 0) {
            System.out.println("更新成功");
        } else {
            System.out.println("更新失败");
        }
        conn.close();
        stat.close();
    }
}

PS:这里的@Test是:??在Java中,@Test?是JUnit测试框架中的一个注解,用于标记一个测试方法。使用?@Test?注解可以告诉JUnit测试运行器(test runner)该方法是一个测试方法,并且应该被执行。(不同@Test直接创建其它类也可以)

?插入一条数据,如果插入成功返回1,失败返回0.? ?

删除语句

    public void test02() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection
                ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=*******");
        Statement stat = conn.createStatement();
        int i = stat.executeUpdate("delete from user where id = 4");
        if(i > 0){
            System.out.println("删除成功");
        }else{
            System.out.println("删除失败");
        }
        conn.close();
        stat.close();
    }
}

(3) 结果集的处理

像上面

   //5 处理执行结果
        while (rs.next() /*游标,下一行有数据返回true,否则false*/){//每一行
            System.out.println(rs.getObject(1));//每一列
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }

这就是结果集的处理的第一种方式;

又比如:

  while (rs.next()){
       System.out.println(rs.getInt("id"));
       System.out.println(rs.getString("name"));
       System.out.println(rs.getInt("age"));
   }

这就是结果集的处理的第二种方式,但是这2种方法都存在问题。因此我们最好将结果集封装起来。

创建一个User类,用于创建对象将数据添加到结果集中。

User类:

public class User {
    private int id;
    private String name;
    private int age;
    private char sex;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    @Override
    public String toString() {
        return "User{" +
                " id= " + id +
                " ,name = " + name+
                " ,age = " + age+
                " ,sex = " + sex+
                " }";
    }

这里的User类实际上就是一个JavaBean(avaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。JavaBean 通过提供符合一致性设计模式的公共方法将内部域暴露成员属性,set和get方法获取。)

封装用集合,不用数组,因为数组大小固定不方便操作,用泛型ArrayList<>实现。

    ResultSet rs = stat.executeQuery("select* from user");
    ArrayList<User> list= new ArrayList<>();
    while(rs.next()){
        User u = new User();
        u.setId(rs.getInt("id"));
        u.setName(rs.getString("name"));
        u.setAge(rs.getInt("age"));
        u.setSex(rs.getString("sex"));
        list.add(u);
    }
    conn.close();
    stat.close();
    rs.close();

(4)处理可能出现的异常

?如上一段代码,如果在ResultSet rs = stat.executeQuery(...);执行完之后出现异常,那么后续代码不会执行,也就是资源不会关闭释放,那么会造成系统负担。因此我们需要在前面加上try /catch /finally的异常捕获机制来避免这种情况的发生。

public class Demo3 {
    @Test
    public void practice01() throws Exception {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection
                    ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=1194006164qwer");
            stat = conn.createStatement();
            rs = stat.executeQuery("select* from user");
        while (rs.next() ){
            System.out.println(rs.getObject(1));
            System.out.println(rs.getObject(2));
            System.out.println(rs.getObject(3));
            System.out.println(rs.getObject(4));
        }
        }catch(Exception e) {
            e.printStackTrace();
        } finally {
            conn.close();
            stat.close();
            rs.close();
    }
  }
}

注意:被try包裹后,finally中的3个变量就没有定义了,需要在开头声明成全局变量。

在关闭conn,stat,rs的时候也要注意可能会出现异常,就像关机的时候进程太多出现关机错误,所以也需要加上捕获异常的措施try-catch-finally。当conn,stat,rs不为null时,尝试正常close,如果失败,就手动置空。

完整格式:

public class Demo3 {
    @Test
    public void practice01() throws Exception {
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection
                    ("jdbc:mysql://localhost:3306/mydb_21?user=root&password=1194006164qwer");
            stat = conn.createStatement();
            rs = stat.executeQuery("select* from user");
            while (rs.next()) {
                System.out.println(rs.getObject(1));
                System.out.println(rs.getObject(2));
                System.out.println(rs.getObject(3));
                System.out.println(rs.getObject(4));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(conn != null){
                try {
                    conn.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    conn = null;
                }
            }
            if(stat != null){
                try{
                    stat.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    stat.close();
                }
            }
            if(rs != null){
                try{
                    rs.close();
                }catch(Exception e){
                    e.printStackTrace();
                }finally {
                    rs.close();
                }
            }
        }
    }
}

文章来源:https://blog.csdn.net/SAKURAjinx/article/details/135388510
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。