首页 > 编程 > Java > 正文

详解Java基础知识――JDBC

2019-11-26 09:05:35
字体:
来源:转载
供稿:网友

JDBC

Java DataBase Connectivity,java数据库连接,为了降低操作数据的难度,java提供jdbc,按照java面向对象特点,对操作进行了很多封装。

JDBC提供了很多接口,然后不同数据库厂商去实现这个接口,到底底层如何去实现,不同的数据库不一样,不同的数据库厂商需要提供接口实现类(驱动类、驱动程序 Driver、驱动)

我们连接不同的数据库,我们只需要使用不同的驱动即可。

J:Java:提供访问数据库的规范(接口),

DBC:接口的实现,厂商去实现这个接口。

JDBC是一种用于执行SQL语句的java api.

版本号

1.1.1 Major. Minor. Build

Major:项目由架构、大规模的变化

Minor:有新功能的时候

Build:编译版本

JDBC开发

Java程序使用第三方提供工具框架,都需要导入jar包

可以通过以下网址搜索找到mysql的相关jar包

https://mvnrepository.com/

下载好jar包后,在于src同级的目录下,建立一个lib文件夹,添加jar包,并添加依赖

代码实现

通过一个简单的案例来实现JDBC的使用

import java.sql.*; public class Demo02 {  public static void main(String[] args) throws ClassNotFoundException, SQLException {    //1注册驱动    Class.forName("com.mysql.jdbc.Driver");    //2建立连接    String url = "jdbc:mysql://localhost:3306/mydb01";    String usernName = "xxx"; //登录数据库的账号    String password = "xxxx"; //登录数据库的密码    Connection conn = DriverManager.getConnection(url, usernName, password);    //3获取执行sQL语句的对象    Statement statement = conn.createStatement();    //4获取数据库返回的结果    String sql = "delete from emp where empno = " +"7499";    String sqlUpdate = "update emp set sal = "+10000+" where empno = " +"7369";      String sqlInsert = "INSERT INTO emp VALUES(2018,/"boss/",/"king/",NULL,/"2018-8-               8/",15000,10000,10);";     //5处理数据集    int i = statement.executeUpdate(sql);    int s = statement.executeUpdate(sqlUpdate);    int ins = statement.executeUpdate(sqlInsert);    System.out.println(i + "行受到影响----删除");    System.out.println(s + "行受到影响----更新");    System.out.println(ins + "行受到影响----插入");    //6关闭连接     statement.close();    conn.close();    }}

使用JDBC的顺序

  1. (1)注册数据库驱动
  2. (2)和数据库建立连接
  3. (3)获取执行SQL语句的对象
  4. (4)获取数据库返回的结果
  5. (5)处理数据集(逻辑代码)
  6. (6)释放资源,关闭连接

常用类

Connection

通过配置文件可以创建一个connect对象

Statement

  1. 通过connect对象获取操作数据库的Statement对象,
  2. 通过它来实现对数据库增删改查操作。
  3. executeQuery():查,返回数据集
  4. executeUpdate():增删改,返回int的数据,影响的行数

ResultSet

数据集,可以理解就是一个集合。

取出数据:

  1. 通过下标:从1开始
  2. 通过字段名:SQL语句中select后面跟的字段,有可能和数据库一样,也可能不一样

JDBC的优化

平时开发和项目上线之后使用的数据库是不一样的,不是同一个

这也就是我们说的,开发环境不一样

开发环境不一样,使用的数据库也就不一样,那么上面的数据库中配置的三要素就要进行修改

而这种修改是人工操作的,人工操作就有存在了失误,而修改之后的.java文件,也要重新编译,这也可能出现错误

假设项目上线,需要以下四个步骤:

测试环境-->修改配置 -->重新编译-->生产环境

如果想要避免上述出现的失误的情况,就要绕开中间的两个步骤

解决的方法就是,配置文件,添加配置文件,将要修改的配置信息存放到配置文件中,每次读取信息从配置文件中读取

而配置文件的位置是固定的,也不会重新编译,这样就可以降低风险

java中用IO流也可以读取配置文件,通过一个专有的类Properties也可以读写配置文件

IO读取配置文件

import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;import java.sql.*;import java.util.Properties; public class IoReadProp {  public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {    //1注册驱动    Class.forName("com.mysql.jdbc.Driver");    String[] para = read();        //2建立连接    String url = para[0];    String usernName = para[1];    String password = para[2];    Connection conn = DriverManager.getConnection(url,usernName,password);        //3获取执行sQL语句的对象    Statement statement = conn.createStatement();        //4获取数据库返回的结果    String sql = "select * from emp";    ResultSet resultSet = statement.executeQuery(sql);     //5处理数据集    try {      while (resultSet.next()){        //.getXXX方法中的参数 1,字段名 2.字段的下标        int empno = resultSet.getInt("empno");        String ename = resultSet.getString("ename");        String job = resultSet.getString(3);        Date date = resultSet.getDate(5);        System.out.println("empno:"+empno+", ename:"+ename+", job:"+job+", date:"+date);      }    }    catch (Exception e){      e.printStackTrace();    }    finally {      //6关闭连接      resultSet.close();      statement.close();      conn.close();    }  }   public static String [] read()throws IOException {    FileReader fr = new FileReader( "E://javalearning//src//jdbc//jdbc.properties" );    //创建 写入 缓冲区    BufferedReader bufferedReader = new BufferedReader( fr );    String [] str = new String[3];    for(int i =0 ;i < 3;i++){      str[i] = bufferedReader.readLine().split("=")[1].replace(";","").trim();    }    bufferedReader.close();    fr.close();    return str;  }}

Properties读取配置文件

import java.io.*;import java.sql.*;import java.util.Iterator;import java.util.Properties; public class PropReadProp {  public static void main(String[] args) throws ClassNotFoundException, SQLException, IOException {    //1注册驱动    Class.forName("com.mysql.jdbc.Driver");    //用户数组存放数据库信息    String[] para = new String[3];      //读取配置文件    int i = 0;    Properties prop = new Properties();    FileInputStream fileInputStream = new FileInputStream("E://javalearning//src//jdbc//jdbc.properties");    InputStream in = new BufferedInputStream(fileInputStream);    prop.load(in);    Iterator<String> it = prop.stringPropertyNames().iterator();    while (it.hasNext()) {      para[i] = prop.getProperty(it.next());      i++;    }    in.close();    //2建立连接    String url = para[0];    String usernName = para[1];    String password = para[2];    Connection conn = DriverManager.getConnection(url, usernName, password);     //3获取执行sQL语句的对象    Statement statement = conn.createStatement();     //4获取数据库返回的结果    String sql = "select * from emp";    ResultSet resultSet = statement.executeQuery(sql);     //5处理数据集    try {      while (resultSet.next()) {        //.getXXX方法中的参数 1,字段名 2.字段的下标        int empno = resultSet.getInt("empno");        String ename = resultSet.getString("ename");        String job = resultSet.getString(3);        Date date = resultSet.getDate(5);        System.out.println("empno:" + empno + ", ename:" + ename + ", job:" + job + ", date:" + date);      }    } catch (Exception e) {      e.printStackTrace();    } finally {      //6关闭连接      resultSet.close();      statement.close();      conn.close();    }  }}

分层DAO

Data Access Object数据访问对象是一个面向对象的数据库接口

会建立一个包:dao,里面的类都是用来操作数据库的。

通常情况下,有几张表,就有几个DAO

分层Entity、bean、pojo

实体,也就是一个一个类,该类里面只有属性,和对应set.get方法

往往一个表一个实体,实体的属性和表的字段有没有关系,名字一般一样,类型相对应

使用逆向工程,通过表导出实体。

Utils 工具类

代替我们去操作一系列的连接关闭等操作

案例:

目录结构如下,

EmpDAO代码如下:

package jdbc.dao;  import jdbc.entity.Emp;import jdbc.utils.JDBCUtils; import java.sql.Connection;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement; public class EmpDAO {   /**   * 根据员工id获取员工信息   */  public Emp getEmpById(Integer id){    Connection connection =null;    Statement statement = null;    ResultSet rs = null;    Emp emp = null;     try {      connection = JDBCUtils.getConnection();      statement = connection.createStatement();      rs = statement.executeQuery("select * from emp where empno='"+id+"'");       while (rs.next()){        emp = new Emp();        int empno = rs.getInt("empno");        emp.setEmpno(empno);         String ename = rs.getString("ename");        emp.setEname(ename);         String job = rs.getString(3);        emp.setJob(job);         String hiredate = rs.getString(5);        emp.setHiredate(hiredate);      }     } catch (SQLException e) {      e.printStackTrace();    }    finally {      JDBCUtils.close(connection,statement,rs);    }    return emp;  }   public Emp getEmpById(String id){    Connection connection =null;    Statement statement = null;    ResultSet rs = null;    Emp emp = null;     try {      connection = JDBCUtils.getConnection();      statement = connection.createStatement();      rs = statement.executeQuery("select * from emp where empno="+id);       while (rs.next()){        emp = new Emp();        int empno = rs.getInt("empno");        emp.setEmpno(empno);         String ename = rs.getString("ename");        emp.setEname(ename);         String job = rs.getString(3);        emp.setJob(job);         String hiredate = rs.getString(5);        emp.setHiredate(hiredate);      }     } catch (SQLException e) {      e.printStackTrace();    }    finally {      JDBCUtils.close(connection,statement,rs);    }    return emp;  }}

entity中的Emp代码如下

package jdbc.entity; public class Emp {  //emp表中的相关属性  private Integer empno;  private String ename;  private String job;  private String mgr;  private String hiredate ;  private double sal;  private double comm;  private Integer deptno;   public Integer getEmpno() {    return empno;  }   public void setEmpno(Integer empno) {    this.empno = empno;  }   public String getEname() {    return ename;  }   public void setEname(String ename) {    this.ename = ename;  }   public String getJob() {    return job;  }   public void setJob(String job) {    this.job = job;  }   public String getMgr() {    return mgr;  }   public void setMgr(String mgr) {    this.mgr = mgr;  }   public String getHiredate() {    return hiredate;  }   public void setHiredate(String hiredate) {    this.hiredate = hiredate;  }   public double getSal() {    return sal;  }   public void setSal(double sal) {    this.sal = sal;  }   public double getComm() {    return comm;  }   public void setComm(double comm) {    this.comm = comm;  }   public Integer getDeptno() {    return deptno;  }   public void setDeptno(Integer deptno) {    this.deptno = deptno;  }   //默认输出方法   @Override  public String toString() {    return "Emp{" +        "empno=" + empno +        ", ename='" + ename + '/'' +        ", job='" + job + '/'' +        ", mgr='" + mgr + '/'' +        ", hiredate='" + hiredate + '/'' +        ", sal=" + sal +        ", comm=" + comm +        ", deptno=" + deptno +        '}';  }}

utils中的JDBCUtils代码如下

package jdbc.utils; import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.sql.*;import java.util.Iterator;import java.util.Properties; public class JDBCUtils {   private static final String URL ;  private static final String USERNAME ;  private static final String PASSWORD ;   static{    String [] parp = null;    try {      parp = PropRead();    } catch (IOException e) {      e.printStackTrace();    }    URL = parp[0];    USERNAME = parp[1];    PASSWORD=parp[2];    try {      Class.forName("com.mysql.jdbc.Driver");    } catch (ClassNotFoundException e) {      e.printStackTrace();    }  }    /**   * 创建连接   */   public static Connection getConnection() throws SQLException {    Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);    return conn;  }   public static void close(Connection co , Statement state, ResultSet rs){    if(rs != null){      try {        rs.close();      } catch (SQLException e) {        e.printStackTrace();      }    }     if(state !=null){      try {        state.close();      } catch (SQLException e) {        e.printStackTrace();      }    }     if(co !=null){      try {        co.close();      } catch (SQLException e) {        e.printStackTrace();      }    }  }    public static void close(Connection co , Statement state){      if(state !=null){      try {        state.close();      } catch (SQLException e) {        e.printStackTrace();      }    }     if(co !=null){      try {        co.close();      } catch (SQLException e) {        e.printStackTrace();      }    }  }   /**   * 读取配置文件   * @return   * @throws IOException   */  public static String [] PropRead()throws IOException {    String[] para = new String[3];    int i = 0;    Properties prop = new Properties();    FileInputStream fileInputStream = new FileInputStream("E://javalearning//src//jdbc//jdbc.properties");    InputStream in = new BufferedInputStream(fileInputStream);    prop.load(in);    Iterator<String> it = prop.stringPropertyNames().iterator();    while (it.hasNext()) {      para[i] = prop.getProperty(it.next());      i++;    }    in.close();    return para;  } }

测试代码如下:

package jdbc; import jdbc.dao.EmpDAO;import jdbc.entity.Emp; import java.util.Scanner; public class Main {  public static void main(String[] args) {    EmpDAO empDAO = new EmpDAO();    System.out.println("请输入ID");    Scanner scanner = new Scanner( System.in );    String value = scanner.nextLine();    Emp emp = empDAO.getEmpById (value);    Emp emp1 = empDAO.getEmpById (7900);    System.out.println(emp);    System.out.println(emp1);  }}

这样就简单实现了一个分层的使用JDBC的案例

SQL注入攻击

根据上述案例,我们可以输入一个员工的id来查找该员工

但是有一个问题,你如何去规定用户的输入,下面给大家看一个现象

我的数据库在中并没有123456789这个id的人,那么为什么还会有结果呢?

就是因为我们的sql语句是根据字符串拼接生成的,当你输入的数据中包含sql关键字时,会被当成sql语句去执行

注意:这是很危险的!

不友好的用户可以根据这个漏洞对你的数据库进行修改,甚至删除你的数据库!

解决方法:PreparedStatement类

PreparedStatement是statement的子类

解决原理:

SQL语句不在拼接,而是通过预处理,也就是说,用户输入的任何内容,都只能作为值,不解析特殊字符。

修改之后打代码如下:

public Emp getEmpById2(String id){    Connection connection =null;    PreparedStatement statement = null;    ResultSet rs = null;    Emp emp = null;     try {      connection = JDBCUtils.getConnection();      String sql = "select * from emp where empno=?";      statement = connection.prepareStatement(sql);      statement.setString(1,id);      rs = statement.executeQuery();      while (rs.next()){        emp = new Emp();        int empno = rs.getInt("empno");        emp.setEmpno(empno);         String ename = rs.getString("ename");        emp.setEname(ename);         String job = rs.getString(3);        emp.setJob(job);         String hiredate = rs.getString(5);        emp.setHiredate(hiredate);      }     } catch (SQLException e) {      e.printStackTrace();    }    finally {      JDBCUtils.close(connection,statement,rs);    }    return emp;  }

再次测试:结果如图

总结:并不是意味着Statement不能用,或者不能SQL拼接

但是如果是前端穿过的来的值需要直接放到SQL语句中,就需要注意。

以上所述是小编给大家介绍的Java基础知识――JDBC详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对武林网网站的支持!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表