JDBC

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。JDBC,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

JDBC

JDBC是什么呢?

Java Database Connection = Java 数据库连接

JDBC就是JAVA帮助我们去操作数据库的一套接口,这个仅仅是接口,没有实现

在这里插入图片描述

如何使用JDBC

1. 注册驱动
    DriverManager.registerDriver(new Driver());
//优化方案
//	Class.forName("com.jdbc.mysql.Driver");
    
2. 获取连接
    Connection connection = DriverManager.getConnection("url","username","password");
    
3. 创建Statement对象,构建sql请求
    Statement statement = connection.getStatement();
    
4. 执行sql,拿到返回结果
    Resultset resultSet = statement.executeQuery("select * from users");
// 增删改 都用这个
//	int affectedRows = statement.executeUpdate("insert into users values ('','')");
    
5. 处理返回结果,解析
    Boolean flag = resultSet.next();
	String name = resultSet.getString("name");

	resultSet.next();
	String name = resultSet.getString("name");
6. 关闭资源

案例一

最原始的JDBC案例

public class JDBCTest1 {
    /**
     * 第一个连接数据库Mysql的JDBC案例
     * @param args
     */

    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;


        try {
            // 1. 注册驱动
            DriverManager.registerDriver(new Driver());
            // 2. 获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc?useSSL=false","root","123456");
            // 3. 创建statement对象
            statement = connection.createStatement();
            // 4. 执行sql语句
            String sql = "select * from t_students";
            resultSet = statement.executeQuery(sql);
            // 5. 结果返回结果
            // 移动游标
            resultSet.next();
            String name = resultSet.getString("name");
            System.out.println("name:" + name);

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {

            // 释放资源
            if (connection != null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (statement != null){
                try {
                    statement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

案例二

完成完整的结果的解析

resultSet = statement.executeQuery(sql);
// 5. 结果返回结果
// 移动游标
while (resultSet.next()) {

    int id = resultSet.getInt("id");
    String name = resultSet.getString("name");
    // 这个地方是列名,不是对象的成员变量名
    Float english = resultSet.getFloat("english");
    String className = resultSet.getString("class");

    Float math = resultSet.getFloat("math");
    Float chinese = resultSet.getFloat("chinese");

    // 赋值
    Student stu = new Student();
    stu.setId(id);
    stu.setName(name);
    stu.setClassname(className);
    stu.setChinese(chinese);
    stu.setMath(math);
    stu.setEnglish(english);

    // 放进List集合中
    students.add(stu);
}

案例三

把连接、用户名、密码都放到配置文件里面去

private static String url;
    private static String username;
    private static String password;

    static {


        try {

            // 加载配置文件
            Properties properties = new Properties();
//            FileInputStream fileInputStream = new FileInputStream("jdbc.properties");
//            properties.load(fileInputStream);


            // 通过类加载器去获取
            ClassLoader classLoader = JDBCTest3.class.getClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream("jdbc.properties");
            properties.load(inputStream);


            // 取值 赋值
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

案例四

升级为JDBCUtils



import com.mysql.jdbc.Driver;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {

    private static String url;
    private static String username;
    private static String password;
    private static String driverName;

    static {

        try {

            // 加载配置文件
            Properties properties = new Properties();
            // 通过类加载器去获取
            ClassLoader classLoader = JDBCTest3.class.getClassLoader();
            InputStream inputStream = classLoader.getResourceAsStream("jdbc.properties");
            properties.load(inputStream);


            // 取值 赋值
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            driverName = properties.getProperty("driverName");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 获取连接
    public static Connection getConnection(){

            Connection connection = null;
            // 1. 注册驱动
            try {
                Class.forName(driverName);  //  = "new Driver()"

//                DriverManager.registerDriver(new Driver());
                // 2. 获取连接
                connection = DriverManager.getConnection(url,username,password);
            } catch (SQLException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        return connection;
    }



    // 释放资源
    public static void releaseSources(Connection connection, Statement statement, ResultSet resultSet){
        // 释放资源
        if (connection != null){
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null){
            try {
                statement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

测试工具 JUNIT

作用:用来测试,测试我们的接口功能是不是正常的

导包
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
写测试类

测试类提供的几个注解执行的顺序

在这里插入图片描述


import org.junit.*;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC {

    /**
     * @Test注解有几个限制
     * 1. 修饰的方法必须是public
     * 2. 修饰的方法无参
     * 3. 修饰的方法无返回值
     */
    @Test
    public void test01() throws SQLException {

        Connection connection = JDBCUtils.getConnection();
        Statement statement = connection.createStatement();

        ResultSet resultSet = statement.executeQuery("select * from t_students");

        while (resultSet.next()){

            String name = resultSet.getString("name");
            System.out.println("name:" + name);
        }

    }

    @Test
    public void test02() throws SQLException {

        Connection connection = JDBCUtils.getConnection();
        Statement statement = connection.createStatement();

        ResultSet resultSet = statement.executeQuery("select * from t_students");

        while (resultSet.next()){

            String name = resultSet.getString("name");
            System.out.println("name:" + name);
        }

    }

    /**
     * 这个什么时候执行? 在@Test注解修饰的方法执行结束之后,执行了几个@Test修饰的方法,就有几次执行
     */
    @After
    public void destory(){

        System.out.println("after");

    }

    /**
     * 这个什么时候执行? 在@Test注解修饰的方法执行结束之前,执行了几个@Test修饰的方法,就有几次执行
     */
    @Before
    public void init(){

        System.out.println("Before");
    }

    /**
     * 在这个测试类结束的时候执行,只会执行一次
     */
    @AfterClass
    public static void afterClass(){
        System.out.println("AfterClass");

    }

    /**
     * 在这个测试类开始的时候执行,只会执行一次
     */
    @BeforeClass
    public static void beforeClass(){
        System.out.println("beforeClass");

    }
}

通过JDBC进行增删改查

import org.junit.*;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

public class TestJDBC2 {

    static Connection connection = null;
    static Statement statement = null;
	
    // 初始化资源 
    @BeforeClass
    public static void init() throws SQLException {

        connection = JDBCUtils.getConnection();
        statement = connection.createStatement();

    }
    
    // 关闭资源
    @AfterClass
    public static void destory(){

        JDBCUtils.releaseSources(connection,statement,null);
    }

    // 新增记录
    @Test
    public void testInsertStu() throws SQLException {

        String sql = "insert into t_students values (8,'柯镇恶','三班',70,20,30)";

        // 返回的结果是影响的行数
        int affectedRows = statement.executeUpdate(sql);

        System.out.println("影响的行数:" + affectedRows);
    }

    // 删除记录
    @Test
    public void testDeleteStu() throws SQLException {

        String sql = "delete from t_students where id > 6";

        // 返回的结果是影响的行数
        int affectedRows = statement.executeUpdate(sql);

        System.out.println("影响的行数:" + affectedRows);

    }

    // 修改记录
    @Test
    public  void testUpdate() throws SQLException {

        String sql = "update t_students set name = '老顽童' where id = 1";
        int affectedRows = statement.executeUpdate(sql);

        System.out.println("影响的行数:" + affectedRows);

    }
    
    // 查询记录
}

对象解析

DriverManager

驱动管理器,提供了两个API

第一个API是注册驱动

DriverManager.registerDriver(new Driver());

第二个API是获取连接

Connection conn = DriverManager.getConnection(url,username,password);

url的写法:jdbc:mysql://localhost:3306/dbName?useSSL=false&characterEncoding=utf-8&serverTimezone=UTC

Connection

这个就是一个连接对象,它表示了我们Java程序和Mysql服务器之间的连接

获取statement对象

Statement statement = connection.createStatement();

还有事务相关的API,以及预编译相关的API

Statement

这个对象用于我们的JDBC向数据库发送SQL语句,并执行获取返回结果

// 使用ResultSet对象来接收查询的结果

ResultSet resultSet = statement.executeQuery(String sql);

// 影响的行数

int affectedRows = statement.executeUpdate(String sql);

ResultSet

这个对象是用来封装查询的结果

resultSet.next(); 这个API就类似于我们的Iterator里面维护的游标,执行一次next() 方法,游标就移动一个位置

resultSet.getInt(String columnName);

resultSet.getString(String columnName);

在这里插入图片描述

还提供了一些API,帮我们快速的操作ResultSet

resultSet.Previous() 移动到前一行

resultSet.beforeFirst() 移动到最前面

resultSet.afterLast(); 移动到最后面

数据库注入问题

我们使用statement.excuteQuery(String sql) 这个API的时候,假如我们的sql是由字符串拼接而来, 那么在我们拼接字符串的时候,假如字符串里面加入了 or 1=1 这样的关键字,那么就会去做全局匹配,可能就会导致我们的sql语句跳过验证逻辑,产生安全隐患


import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 * 模拟数据库注入的问题
 */
public class JDBCTest3 {

    static Connection connection = null;
    static Statement statement = null;

    @BeforeClass
    public static void testBefore() throws SQLException {

        connection = JDBCUtils.getConnection();
        statement = connection.createStatement();

    }
    @AfterClass
    public static void destory(){

        JDBCUtils.releaseSources(connection,statement,null);
    }




    // 查询用户名和密码
    public Boolean login(String username,String password) {


//        String sql = "select * from user where username = '"+ username  + "' and password  = '"+password + "'";

        String sql = "select * from user where username = %s and password = %s";
        String newUsername = "'" + username + "'";
        String newPassword = "'" + password + "'";
//
        String trueSql = String.format(sql, newUsername, newPassword);

        ResultSet resultSet = null;
        try {
            resultSet = statement.executeQuery(trueSql);

            // resultSet.next() 如果为true,那么就表示登录成功,也就是说这个时候数据库里面有数据
            if (resultSet.next()) {
                System.out.println("匹配上了,登录成功,用户名:" + resultSet.getString("username"));
                return true;
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }


        return false;
    }

    @Test
    public void testLogin(){


        Boolean ret = login("l", "l");

        System.out.println("ret:" + ret);

    }

    /**
     * 数据库的注入问题
     *
     * 发现在密码后面加入 1=1 不安全,这种问题就是数据注入问题
     */
    @Test
    public void testLoginUnnormal(){


        Boolean ret = login("jklsfjkl", "asjkldjl' or '1=1");

        // select * from user where username = 'jklsfjkl' and password = 'asjkldjl' or '1=1';

        System.out.println("ret:" + ret);

    }
}

解决办法: 使用 connection.prepareStatement(); 来解决这个安全隐患的问题

prepareStatement

提供了几个API

@Test
    public void testPrepareStatementQuestion() throws SQLException {

//        Statement statement = connection.createStatement();
        // ? 表示占位符
        // 这一句话,会对我们的sql语句去进行预编译,后续我们只需要把 ?填充进来即可,填充进来的都是值,不会是我们的关键字
        PreparedStatement pst = connection.prepareStatement("select * from user where username = ? and password = ?");

        pst.setString(1,"l");
        pst.setString(2,"'l' or 1=1 ");

        // 执行sql语句,获取结果
        ResultSet resultSet = pst.executeQuery();

        while(resultSet.next()) {

            String username = resultSet.getString("username");
            String password = resultSet.getString("password");
            String gender = resultSet.getString("gender");
            int id = resultSet.getInt("id");

            System.out.println("id : " + id + ", username : " + username + ", password:" + password + ", gender:" + gender);

        }


    }


// 结论,我们通过执行测试,发现并没有找到对应的用户,说明我们这里通过这种预编译占位的方式,可以解决数据库的注入问题

基本使用:和statement很类似。只是需要去占位

批处理

statement的批处理

Module复制步骤

  • 第一步,点击需要复制的module

在这里插入图片描述

  • 第二步,复制文件,删除.iml文件和targert文件

在这里插入图片描述

  • 第三步 修改文件夹的名字和pom文件里面artifactId 的名字,让他们保持一致

  • 第四步 导入

    • 点击projectStrcture
      在这里插入图片描述

    • 点击‘ + ’号,导入项目,选择importModule

在这里插入图片描述

  • 选中我们需要导入的pom文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l18SGEX8-1615300203863)(JDBC.assets/image-20210309114216254.png)]

  • 点击next 和finish 就可以了

  • 检查项目的各个路径是否正确,例如java目录有没有被识别为source目录,resources目录有没有被识别为resources目录

在这里插入图片描述

这样就导入成功了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181125.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!