JDBC数据库连接基础知识

版权声明:------------------------------这个世界上只有一种成功,就是按照自己想要的方式度过一生--------------------------- https://blog.csdn.net/qq_44238142/article/details/88605985

简介

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。JDBC其实就是java定义的一套和数据库建立连接的规范(接口),各家数据库厂商,想要Java去操作自家数据库,就必须实现这套接口,我们把数据库厂商写的这套实现类,叫做数据库驱动。
在这里插入图片描述
返回顶部

JDBC的用途

JDBC 可做三件事:与数据库建立连接、发送操作数据库的语句并处理结果。
返回顶部

JDBC快速入门

  1. 导入数据库的驱动jar包
  2. 加载驱动jar包
  3. 获取连接对象
  4. 获取操作对象
  5. 开始操作
  6. 释放资源

案例演示-JDBC

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        //1.导入数据库的驱动jar包
        //将下载好的驱动包复制到project下新建的lib文件夹下,右键lib,点击Add as Library
        //2.加载驱动jar包,通过放射的方式
        //可以省略不写,注册驱动这个动作是Driver里面有个静态代码块在做
   		/*
 		static {
            	try {
                	DriverManager.registerDriver(new Driver());
           		 } catch (SQLException var1) {
                	throw new RuntimeException("Can't register driver!");
            	}
       		 }
        */
        Class.forName("com.mysql.jdbc.Driver");
        //3.获取连接对象
        //url的格式:jdbc:mysql://ip地址:端口/库名
        //本地连接可以简写 主机名和端口可以省略不写
        //String url = "jdbc:mysql:///0316test"
        String url = "jdbc:mysql://localhost:3306/0316test";
        //数据库用户名
        String username = "root";
        //密码
        String password = "123456";
        //把这三个参数传入,返回连接对象
        //java.sql 接口 Connection 与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
        Connection connection = DriverManager.getConnection(url, username, password);
        //4.获取操作对象
        //Statement createStatement () 创建一个 Statement 对象来将 SQL 语句发送到数据库。
      	// Statement 用于执行静态 SQL 语句并返回它所生成结果的对象。
        Statement statement = connection.createStatement();
        //5.执行SQL语句
        //给0316test库中的emp表中插入一条数据
        String sql = "INSERT INTO emp VALUES (1006,'李四','工头',200);";
        //执行SQL语句
        //statement.execute()用来执行所有类型的SQL语句,返回true 或 false
         //如果第一个结果为 ResultSet 对象,则返回 true;如果其为更新计数或者不存在任何结果,则返回 false
        //statement.executeUpdate();用来执行DML,DDL语句,返回影响的行数
        //statement.executeQuery(); 用来执行DQl语句 用于产生单个结果集的语句,例如 SELECT 语句。
        int i = statement.executeUpdate(sql);//返回改变行数
        //判断是否插入成功
        if (i > 0) {
            System.out.println("success");
        } else {
            System.out.println("file");
        }
        //6.释放资源
        connection.close();
        statement.close();
    }
}

返回顶部

结果集对象 ResultSet

结果集对象,是我们执行了查询语句之后返回的一个查询结果对象
ResultSet 对象具有指向其当前数据行的光标。 最初,光标被置于第一行之前。next 方法将光标移动到下一行;因为该方法在 ResultSet 对象没有下一行时返回 false,所以可以在 while循环中使用它来迭代结果集。
我们现在数据库中新建一张学生表并插入数据:

CREATE TABLE `students` (                                                                                                         
            `sname` varchar(20) DEFAULT NULL,                                                                                               
            `sage` int(11) DEFAULT NULL                                                                                                     
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8 
INSERT INTO students VALUES("张三",19);
INSERT INTO students VALUES("李四",20);
INSERT INTO students VALUES("王五",18);

-- 学生表
sname     sage  
------  --------
张三            19
李四            20
王五            18

现在用java来操作这张表:

import java.sql.*;
import java.util.ArrayList;

public class JDBCDemo2 {
    public static void main(String[] args) throws Exception {
        ArrayList<Students> list = new ArrayList<>();
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///0316test", "root", "123456");
        String sql = "select * from students";
        Statement statement = conn.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        // ResultSet 结果集对象
        //表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
        // 可以用next方法来迭代结果集
        while (resultSet.next()) {
            //一行一行来获取值,1和2表示每行第一列和第二列的值
            String sname1 = resultSet.getString(1);
            int sage1 = resultSet.getInt(2);
            //System.out.println(sname1+"----"+sage1);
            // 你也可以通过列名来获取值
            String sname2 = resultSet.getString("sname");
            int sage2 = resultSet.getInt("sage");
            //System.out.println(sname2+"----"+sage2);
            //我们从数据库中取出数据,是为了使用这些数据,那么我们新建一个学生类和一张list表来存储学生对象
            Students s = new Students(sname1, sage1);
            list.add(s);
        }
        System.out.println(list);
        //[Students{name='张三', age=19}, Students{name='李四', age=20}, Students{name='王五', age=18}]
        //    释放资源
        conn.close();
        statement.close();
        resultSet.close();
    }
}

这是学生类:

/**
 * @Author: 伟酱
 * @CreateTime: 2019-03-16 21:44
 * @Description: TODO
 */
public class Students {
    private String name;
    private int age;

    public Students() {

    }

    public Students(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "Students{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

返回顶部

预编译对象

下面来看些关于数据库安全方面的知识,一个案例:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;

public class JDBCDemo3 {
    public static void main(String[] args) throws Exception {
        //    students表中已经存储了三行数据,现在我们通过java来查询

        //我想要输入学生姓名,然后查找学生信息
        System.out.println("请输入姓名:");
        Scanner scanner = new Scanner(System.in);
        String sname = scanner.nextLine();
        
		////sname= "1'='1' or '1'='1";
		
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///0316test", "root", "123456");
        String sql = "select * from students where sname='" + sname + "'";
        Statement statement = conn.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        if (resultSet.next()) {
            System.out.println("查找成功");
        } else {
            System.out.println("没有找到");
        }
         //    别忘了释放资源
        conn.close();
        statement.close();
        resultSet.close();
    }
}

这段代码可以通过在java控制台输入学生姓名去数据库查找信息并返回结果我们来测试一下,这是数据库中已经有的数据:

sname     sage  
------  --------
张三            19
李四            20
王五            18

  • case1
请输入姓名:
王麻子
没有找到
  • case2
请输入姓名:
张三
查找成功
  • case3
请输入姓名:
1'='1' or '1'='1
查找成功

我们输入这样的字符串竟然返回了查找成功的结果!!
我们称之为SQL注入(所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。)
我们也可以在上面的代码中取消键盘输入插入这样一行代码:

sname= "1'='1' or '1'='1";

相当于在数据库中执行了这样一段SQL语句:

SELECT * FROM students WHERE sname= '1'='1' or '1'='1';
-- 它会返回所有数据 

和上面的结果是一致的,都会返回意料之外的结果。其实在开发过程中,我们并不推荐动态拼串,但是,在必要时,我们可以使用预编译来防止注入。

  • prepareStatement
public interface PreparedStatement
extends Statement表示预编译的SQL语句的对象。 
SQL语句已预编译并存储在PreparedStatement对象中。
  • 给?赋值
void setString(int parameterIndex,
               String x)
        throws SQLException
        
将指定的参数设置为给定的Java String值。 
当它发送到数据库时,驱动程序将其转换为SQL VARCHAR或LONGVARCHAR值
(取决于参数相对于VARCHAR值的驱动程序限制的大小)。 

参数 
parameterIndex - 第一个参数是1,第二个是2... 
x - 参数值

来看升级后的代码:

import java.sql.*;
import java.util.Scanner;

public class JDBCDemo4 {
    public static void main(String[] args) throws Exception {
        System.out.println("请输入姓名:");
        Scanner scanner = new Scanner(System.in);
        String sname = scanner.nextLine();
        
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql:///0316test", "root", "123456");
        //把需要拼串的内容用英文?代替,把sql语句预编译,然后再给?赋值
        String sql = "select * from students where sname=?";
        PreparedStatement preparedStatement = conn.prepareStatement(sql);
        preparedStatement.setString(1,sname);
        //注意这里不要再传参
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) {
            System.out.println("查找成功");
        } else {
            System.out.println("没有找到");
        }

    //    释放资源
        conn.close();
        preparedStatement.close();
        resultSet.close();
    }
}

再来测试:

请输入姓名:
1'='1' or '1'='1
没有找到

返回顶部

改写为工具类

每次都要获取数据库连接对象很麻烦,我们可以把这段代码封装一下,写成一个工具类,让它自动返回连接对象,但是传进去的三个参数不能写死,我们可以把它写成配置文件,在工具类加载时去读取它,如果要对参数进行修改,直接改配置文件就行。
这里读取配置文件有很多方法:

  1. file 文件
  • 先在project文件夹下新建一个file文件:register
  • 这是文件中的内容,可以在这里修改用户名,密码,和url
    username=root;password=123456;url=jdbc:mysql://localhost:3306/0316test;com.mysql.jdbc.Driver;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;

public class JDBCUtils {
    private static String username;
    private static String password;
    private static String url;

    //1.构造
    public JDBCUtils() {

    }
	//静态代码块,截取url,username,password
    static {
        try {
            FileInputStream in = new FileInputStream("E:\\my0316\\register");
            byte[] bytes = new byte[1024];
            int len = in.read(bytes);
            String s = new String(bytes, 0, len);
            String[] split = s.split(";");
            username = split[0].split("=")[1];
            password = split[1].split("=")[1];
            url = split[2].split("=")[1];
            Class.forName(split[3]);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //2.我们提供公共的静态方法,来返回一个连接对象
    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }

    //3.释放资源-有ResultSet
    public static void close(Connection conn, Statement statement, ResultSet resultSet) throws SQLException {
        if (conn != null) {
            conn.close();
        }

        if (statement != null) {
            statement.close();
        }
        if (resultSet != null) {
            resultSet.close();
        }

    }
	//重载,释放资源-没有RresultSet
    public static void close(Connection conn, Statement statement) throws SQLException {
        if (conn != null) {
            conn.close();
        }

        if (statement != null) {
            statement.close();
        }

    }
}

  1. properties文件
  • 新建properties文件:register.properties

  • 输入:

  • username=root
    password=123456
    url=jdbc:mysql:///0316test
    driverclass=com.mysql.jdbc.Driver

// 替换上面的静态代码块即可,其实目的都是读取到正确的连接参数
static{
	try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("E:\\my0316\\register.properties")); //注意配置文件的路径
            Class.forName(properties.getProperty("driverclass", "com.mysql.jdbc.Driver"));//给个默认值
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            url = properties.getProperty("url");        
        } catch (Exception e) {
            e.printStackTrace();
        }
   	}

我们来测试一下工具类:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JDBCDemo {
    public static void main(String[] args) throws SQLException {
    	//通过工具类获取连接对象
        Connection connection = JDBCUtils.getConnection();
        String sql = "insert into users values(?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,"张三");
        preparedStatement.setString(2,"123456");
        int i = preparedStatement.executeUpdate();
        if (i>0) {
            System.out.println("成功");
        } else {
            System.out.println("失败");
        }
        //释放资源
        connection.close();
    }
}

返回:

成功

返回顶部

猜你喜欢

转载自blog.csdn.net/qq_44238142/article/details/88605985