栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

JDBC(Java数据库连接)

JDBC(Java数据库连接)

1、JDBC快速入门 1.1 JDBC的概念

        JDBC(Java Database Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系型数据库提供统一访问,它是由一组用Java语言编写的类和接口组成的。

1.2 JDBC的本质

        其实就是java官方提供的一套规范(接口)。用于帮助开发人员快速实现不同关系型数据库的连接!

1.3 JDBC的快速入门程序 1.3.1 导入jar包 1.3.2 注册驱动 
Class.forName("com.mysql.jdbc.Driver");
1.3.3 获取连接
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db2", "root", "root");
1.3.4 获取执行者对象
Statement stat = con.createStatement();
1.3.5 执行sql语句,并接收返回结果
String sql = "SELECt * FROM user";
ResultSet rs = stat.executeQuery(sql);
1.3.6 处理结果
while(rs.next()) {
    System.out.println(rs.getInt("id") + "t" + rs.getString("name"));
}
1.3.7 释放资源
con.close();
stat.close();
rs.close();
2、JDBC各个功能类详解 2.1 DriverManager
  • DriverManager:驱动管理对象

    • 注册驱动(告诉程序该使用哪一个数据库驱动)

      • static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager

      • 写代码使用:Class.forName("com.mysql.jdbc.Driver");

      • 通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块

      static {
          try {
              java.sql.DriverManager.registerDriver(new Driver());
          } catch (SQLException E) {
              throw new RuntimeException("Can't register driver!");
          }
      }
      • 注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。在jar包中,存在一个java.sql.Driver配置文件,文件中指定了com.mysql.jdbc.Driver

    • 获取数据库连接(获取到数据库的连接并返回连接对象)

      • static Connection getConnection(String url, String user, String password);

        • 返回值:Connection数据库连接对象

        • 参数

          • url:指定连接的路径。语法:jdbc:mysql://ip地址(域名):端口号/数据库名称

          • user:用户名

          • password:密码

2.2 Connection
  • Connection:数据库连接对象

    • 获取执行者对象

      • 获取普通执行者对象:Statement createStatement();

      • 获取预编译执行者对象:PreparedStatement prepareStatement(String sql);

    • 管理事务

      • 开启事务:setAutoCommit(boolean autoCommit); 参数为false,则开启事务。

      • 提交事务:commit();

      • 回滚事务:rollback();

    • 释放资源

      • 立即将数据库连接对象释放:void close();

2.3 Statement
  • Statement:执行sql语句的对象

    • 执行DML语句:int executeUpdate(String sql);

      • 返回值int:返回影响的行数。

      • 参数sql:可以执行insert、update、delete语句。

    • 执行DQL语句:ResultSet executeQuery(String sql);

      • 返回值ResultSet:封装查询的结果。

      • 参数sql:可以执行select语句。

    • 释放资源

      • 立即将执行者对象释放:void close();

2.4 ResultSet
  • ResultSet:结果集对象

    • 判断结果集中是否还有数据:boolean next();

      • 有数据返回true,并将索引向下移动一行

      • 没有数据返回false

    • 获取结果集中的数据:XXX getXxx("列名");

      • XXX代表数据类型(要获取某列数据,这一列的数据类型)

      • 例如:String getString("name"); int getInt("age");

    • 释放资源

      • 立即将结果集对象释放:void close();

3、JDBC案例student学生表的CRUD 3.1 数据准备
  • 数据库和数据表

-- 创建db14数据库
CREATE DATAbase db14;
​
-- 使用db14数据库
USE db14;
​
-- 创建student表
CREATE TABLE student(
    sid INT PRIMARY KEY AUTO_INCREMENT, -- 学生id
    NAME VARCHAr(20),                   -- 学生姓名
    age INT,                            -- 学生年龄
    birthday DATE                       -- 学生生日
);
​
-- 添加数据
INSERT INTO student VALUES (NULL,'张三',23,'1999-09-23'),(NULL,'李四',24,'1998-08-10'),(NULL,'王五',25,'1996-06-06'),(NULL,'赵六',26,'1994-10-20');
  • 实体类

    • Student类,成员变量对应表中的列

    • 注意:所有的基本数据类型需要使用包装类,以防null值无法赋值

package com.itheima02.domain;

import java.util.Date;

public class Student {
    private Integer sid;
    private String name;
    private Integer age;
    private Date birthday;

    public Student() {
    }

    public Student(Integer sid, String name, Integer age, Date birthday) {
        this.sid = sid;
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", name='" + name + ''' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}
3.2 需求一:查询全部
  • 持久层

@Override
public ArrayList findAll() {
    ArrayList list = new ArrayList<>();
    Connection con = null;
    Statement stat = null;
    ResultSet rs = null;
    try{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
​
        //2.获取数据库连接
        con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");
​
        //3.获取执行者对象
        stat = con.createStatement();
​
        //4.执行sql语句,并且接收返回的结果集
        String sql = "SELECT * FROM student";
        rs = stat.executeQuery(sql);
​
        //5.处理结果集
        while(rs.next()) {
            Integer sid = rs.getInt("sid");
            String name = rs.getString("name");
            Integer age = rs.getInt("age");
            Date birthday = rs.getDate("birthday");
​
            //封装Student对象
            Student stu = new Student(sid,name,age,birthday);
​
            //将student对象保存到集合中
            list.add(stu);
        }
​
    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        //6.释放资源
        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
​
        if(stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
​
        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //将集合对象返回
    return list;
}
  • 业务层
@Override
public ArrayList findAll() {
    return dao.findAll();
}
  • 控制层
@Test
public void findAll() {
    ArrayList list = service.findAll();
    for(Student stu : list) {
        System.out.println(stu);
    }
}
3.3 需求二:条件查询
  • 持久层

@Override
public Student findById(Integer id) {
    Student stu = new Student();
    Connection con = null;
    Statement stat = null;
    ResultSet rs = null;
    try{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取数据库连接
        con = DriverManager.getConnection("jdbc:mysql://192.168.59.129:3306/db14", "root", "itheima");

        //3.获取执行者对象
        stat = con.createStatement();

        //4.执行sql语句,并且接收返回的结果集
        String sql = "SELECt * FROM student WHERe sid='"+id+"'";
        rs = stat.executeQuery(sql);

        //5.处理结果集
        while(rs.next()) {
            Integer sid = rs.getInt("sid");
            String name = rs.getString("name");
            Integer age = rs.getInt("age");
            Date birthday = rs.getDate("birthday");

            //封装Student对象
            stu.setSid(sid);
            stu.setName(name);
            stu.setAge(age);
            stu.setBirthday(birthday);
        }

    } catch(Exception e) {
        e.printStackTrace();
    } finally {
        //6.释放资源
        if(con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //将对象返回
    return stu;
}
  •  业务层
@Override
public Student findById(Integer id) {
    return dao.findById(id);
}
  •  控制层
@Test
public void findById() {
    Student stu = service.findById(3);
    System.out.println(stu);
}
5、SQL注入攻击 5.1 sql注入攻击的演示
  • 在登录界面,输入一个错误的用户名或密码,也可以登录成功

 

5.2 sql注入攻击的原理
  • 按照正常道理来说,我们在密码处输入的所有内容,都应该认为是密码的组成

  • 但是现在Statement对象在执行sql语句时,将一部分内容当做查询条件来执行了

5.3 PreparedStatement的介绍
  • 预编译sql语句的执行者对象。

    • 在执行sql语句之前,将sql语句进行提前编译。明确sql语句的格式后,就不会改变了。剩余的内容都会认为是参数!

    • sql语句中的参数使用?作为占位符

  • 为?参数赋值的方法:setXxx(参数1,参数2);

    • Xxx代表:数据类型

    • 参数1:?的位置编号(编号从1开始)

    • 参数2:?的实际参数

  • 执行sql语句的方法

    • 执行insert、update、delete语句:int executeUpdate();

    • 执行select语句:ResultSet executeQuery();

5.4 PreparedStatement的使用
@Override
public User findByLoginNameAndPassword(String loginName, String password) {
    //定义必要信息
    Connection conn = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    User user = null;
    try {
        //1.获取连接
        conn = JDBCUtils.getConnection();
        //2.创建操作SQL对象
        String sql = "SELECT * FROM user WHERe loginname=? AND password=?";
        pstm = conn.prepareStatement(sql);
        //3.设置参数
        pstm.setString(1,loginName);
        pstm.setString(2,password);
        System.out.println(sql);
        //4.执行sql语句,获取结果集
        rs = pstm.executeQuery();
        //5.获取结果集
        if (rs.next()) {
            //6.封装
            user = new User();
            user.setUid(rs.getString("uid"));
            user.setUcode(rs.getString("ucode"));
            user.setUsername(rs.getString("username"));
            user.setPassword(rs.getString("password"));
            user.setGender(rs.getString("gender"));
            user.setDutydate(rs.getDate("dutydate"));
            user.setBirthday(rs.getDate("birthday"));
            user.setLoginname(rs.getString("loginname"));
        }
        //7.返回
        return user;
    }catch (Exception e){
        throw new RuntimeException(e);
    }finally {
        JDBCUtils.close(conn,pstm,rs);
    }
}
7、数据库连接池 7.1 数据库连接池的概念
  • 数据库连接背景

    • 数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。

  • 数据库连接池

    • 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。这项技术能明显提高对数据库操作的性能。

  • 数据库连接池原理

7.2 Data Source 7.2.1 DataSource接口概述
  • javax.sql.DataSource接口:数据源(数据库连接池)。Java官方提供的数据库连接池规范(接口 )
  • 如果想完成数据库连接池技术,就必须实现DataSource接口
  • 核心功能:获取数据库连接对象:Connection getConnection();
7.2.2 自定义数据库连接池
  1. 定义一个类,实现DataSource接口
  2. 定义一个容器,用于保存多个Connection连接对象
  3. 定义静态代码块,通过jdbc工具类获取10个连接保存到容器中
  4. 重写getConnection方法,从容器中获取一个连接并返回
  5. 定义getSize方法,用于获取连接池容器的大小并返回
 7.2.3 自定义数据库连接池的测试
  1. 创建连接池对象
  2. 获取数据库连接对象
  3. 查询学生表全部信息,并将查询的结果进行处理
  4. 释放资源
7.2.4 归还连接

1、继承(无法解决)

  • 通过打印连接对象,发现DriverManager获取的连接实现类是JDBC4Connection。

  • 自定义一个类,继承JDBC4Connection这个类,重写close()方法,完成连接对象的归还。

 2、继承方式归还数据库连接的实现步骤

  1. 定义一个类,继承JDBC4Connection
  2. 定义Connection连接对象和连接池容器对象的成员变量
  3. 通过有参构造方法完成对成员变量的赋值
  4. 重写close方法,将连接对象添加到池中

3、继承方式归还数据库连接存在的问题

        通过查看JDBC工具类获取连接的方法发现:我们虽然自定义了一个子类,完成了归还连接的

操作。但是DriverManager获取的还是JDBC4Connection这个对象,并不是我们的子类对象。

而我们又不能整体去修改驱动包中类的功能,所以继承这种方式行不通!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/344668.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号