Java - jdbc

195 阅读3分钟

使用idea连接数据库

截屏2022-02-06 下午6.17.28.png

jdbc

我们的程序会通过 数据库驱动,和数据库打交道

sun公司为了简化开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,俗称jdbc,这些规范的实现由具体的厂商(MySQL,oracle)去做。

java.sql javax.sql 还需要导入一个数据库驱动包

第一个Java的jdbc程序

用idea去连数据库

  1. 创建测试数据库:

    CREATE DATABASE `jdbcStudy` CHARACTER SET utf8 COLLATE utf8_general_ci;
    
    USE `jdbcStudy`;
    
    CREATE TABLE `users`(
    `id` INT PRIMARY KEY,
    `NAME` VARCHAR(40),
    `PASSWORD` VARCHAR(40),
    `email` VARCHAR(60),
    birthday DATE
    );
    
    INSERT INTO `users`(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)
    VALUES(1,'zhangsan','123456','zs@sina.com','1980-12-04'),
    (2,'lisi','123456','lisi@sina.com','1981-12-04'),
    (3,'wangwu','123456','wangwu@sina.com','1979-12-04')
    
  2. 导入数据库驱动

    在idea中导入jar包,并 add as library

    在idea中用代码写,和在可视化工具中直接去操作数据库,是一样的

  3. java的完整代码

    package com.kuang.lesson01;
    
    import java.sql.*;
    
    /*
        以下代码,思考每一步在可视化工具 tablePlus 中是怎么操作的
    */
    
    // 我的第一个JDBC程序
    public class JdbcFirstDemo {
        public static void main(String[] args) throws ClassNotFoundException, SQLException {
            // 1. 加载驱动
            Class.forName("com.mysql.cj.jdbc.Driver"); // 固定写法,加载驱动
    
            // 2. 用户信息和url
                // useUnicode=true&characterEncoding=utf8&useSSL=true; 固定写法
                // jdbcStudy是数据库名
            String url = "jdbc:mysql://localhost:3306/jdbcStudy?useUnicode=true&characterEncoding=utf8&useSSL=true"; // 这是MySQL驱动的写法
            String username = "root";
            String password = "123456";
    
            // 3.连接成功。返回数据库对象
                // Connection 代表数据库
            Connection connection = DriverManager.getConnection(url, username, password);
    
            // 4. 执行SQL的对象
                // Statement 代表执行SQL的对象
            Statement statement = connection.createStatement();
    
            // 5. 用 执行SQL的对象 去 执行SQL;可能存在结果,查看返回的结果
            String sql = "SELECT * FROM `users`";
                // ResultSet 代表返回的结果集
            ResultSet resultSet = statement.executeQuery(sql);
    
            while (resultSet.next()) { //如果结果集里面存在下一个数据
                System.out.println("id="+resultSet.getObject("id"));
                System.out.println("name="+resultSet.getObject("NAME"));
                System.out.println("pwd="+resultSet.getObject("PASSWORD"));
                System.out.println("email="+resultSet.getObject("email"));
                System.out.println("birthday="+resultSet.getObject("birthday"));
            }
    
            // 6. 释放连接
            resultSet.close();
            statement.close();
            connection.close();
        }
    }
    

Connection对象 代表数据库,可以: 数据库设置自动提交 connection.setAutoCommit() 事务提交 connection.commit() 事务回滚 connection.rollback()

Statement对象 执行SQL的对象: 用于向数据库发送sql语句,可以完成度数据库的增删改查 statement.executeQuery(sql); // 查询,返回结果集ResultSet statement.executeUpdate(sql); // 更新、插入、删除,都是用这个。返回一个受影响的行数

PreparedStatement 也是执行SQL的对象

ResultSet对象 查询的结果集,封装了所有的查询结果 获得指定的数据类型 resultSet.getObject() // 不知道列类型的情况下使用 resultSet.getString() // 字符串类型

遍历,指针 resultSet.next()

编写工具类,去优化这个jdbc程序

工具类 JdbcUtils.java

db.properties ...

SQL注入

SQL会被拼接

PreparedStatement对象

PreparedStatement对象和Statement对象: PreparedStatement对象可以防止SQL注入,并且效率更高

对比一下这2种对象的写法:

Statement对象

package com.kuang.lesson02.utils;

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

// 用工具类简化
public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();
            String sql = "INSERT INTO `users`(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)\n" +
                    "VALUES(5,\"lake5\",\"123456\",\"l@qq.com\",\"1979-12-04\");";
            int i = st.executeUpdate(sql);
            if(i!=0) {
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}

PreparedStatement对象

package com.kuang.lesson03;

import com.kuang.lesson02.utils.JdbcUtils;

import java.sql.*;
import java.util.Date;

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try {
            conn = JdbcUtils.getConnection();

            // 与 Statement对象 的区别:
            String sql = "INSERT INTO `users`(`id`,`NAME`,`PASSWORD`,`email`,`birthday`)\n" +
                    "VALUES(?,?,?,?,?);";// 使用?占位符站位参数,可以避免SQL注入
            st = conn.prepareStatement(sql);

            // 手动给参数赋值
            st.setInt(1, 5); //1,代表第一个参数,即第一个?占位符
            st.setString(2, "lake4_by_PreparedStatement");
            st.setString(3, "123456");
            st.setString(4, "ww@qq.com");
//            注意点:sql.Date 数据库
//            util.Date Java
//            new Date().getTime() 获得时间戳
            st.setDate(5, new java.sql.Date(new Date().getTime()));
            // 执行
            int i = st.executeUpdate();

            if (i != 0) {
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn, st, null);
        }
    }
}

TODO: 只写了 insert,回头练下 delete, update, select (42集)

PreparedStatement 防止 SQL注入的本质: 把传递进来的参数当作字符,假设其中存在转义字符,就直接忽略。所以推荐使用 PreparedStatement,而不是 Statement。