JDBC(连接数据库)

本文介绍了JDBC的基本概念,包括连接数据库、SQL查询封装、防止SQL注入的预编译语句、编写实用工具类、批处理操作、存储过程调用、数据库内置函数使用及自增长键获取。通过实例演示了如何在Java中安全地进行数据库操作。
摘要由CSDN通过智能技术生成
  • JDBC入门案例
  • JDBC连接介绍
  • 使用JDBC查询数据,并封装到对象中
  • 模拟登录(存在SQL注入风险)
  • 使用预编译操作对象防止SQL注入
  • 编写JDBC工具类
  • 批处理
  • 在Java程序中调用存储过程 
  • java中调用数据库的内置函数
  • 自增长键


1.JDBC入门案例

JDBC:Java DataBase Connectivity Java 连接数据库
JDBC,其实就是Java定义的一套和数据库建立连接的规范(接口),那么各家数据库厂商,想要Java去操作各家的数据库,必须实现这套接口,我们把数据库厂商写的这套实现类,称之为数据库驱动。

MySQL 8.0 注意以下
加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");

String url = "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8";
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;

public class MyTest {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        /*
         *  JDBC: Java连接数据库, 他是一个规范,也就是说Java提供的一套接口
         *
         * JDBC:Java DataBase Connectivity Java 连接数据库
            JDBC,其实就是Java定义的一套和数据库建立连接的规范(接口),
*                那么各家数据库厂商,想要Java去操作各家的数据库,必须实现这套接口,我们把数据库厂商写的这套实现类,称之为数据库驱动。
         * */

        //JDBC的快速入门
        //1. 引入MySQL的数据库驱动jar包,记得依赖
        //2. 加载驱动
        //3. 获取连接对象
        //4. 获取操作对象
        //5. 执行SQL语句
        //6. 释放资源


        //加载驱动
        Class.forName("com.mysql.jdbc.Driver");

        //获取连接对象,用户名,密码,库的路径
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");

        //获取操作对象
        Statement statement = conn.createStatement();

        //使用操作对象,发送sql语句

        String sql = "insert into user values(null,'jdbc',password('123456'))";
        //执行增删改的SQL语句,返回的是你影响的行数
        int i = statement.executeUpdate(sql);
        if (i > 0) {
            System.out.println("插入成功");
        } else {
            System.out.println("插入失败");
        }

        //释放资源
        conn.close();
        statement.close();


        //    MySQL 8.0 注意以下

        //加载驱动
        //Class.forName("com.mysql.cj.jdbc.Driver");

        //  String url = "jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF-8&userSSL=false&serverTimezone=GMT%2B8";
    }
}


2.JDBC连接介绍

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

public class MyTest2 {
    public static void main(String[] args) throws Exception {
        //1.加载驱动 其实也可以省略不写,建议写上
        Class<?> aClass = Class.forName("com.mysql.jdbc.Driver");
      /*  public class Driver extends NonRegisteringDriver implements java.sql.Driver {
            public Driver() throws SQLException {
            }
            //静态代码块
            static {
                try {
                    //注册驱动
                    //static void registerDriver(Driver driver)  向 DriverManager 注册给定驱动程序。
                    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
                } catch (SQLException var1) {
                    throw new RuntimeException("Can't register driver!");
                }
            }
        }*/

        // 2.获取连接对象
        //获取连接对象,用户名,密码,库的路径
        //java.sql
        // 类 DriverManager 管理一组 JDBC 驱动程序的基本服务。


        // static Connection getConnection (String url, String user, String password)
        // 试图建立到给定数据库 URL 的连接。
        //如果你是本地连接:可以省略 localhost:3306
        String url = "jdbc:mysql:///mydb";
        Connection conn = DriverManager.getConnection(url, "root", "123456");

        // Connection 连接对象
        // java.sql 接口 Connection 与特定数据库的连接(会话)。在连接上下文中执行 SQL 语句并返回结果。
        //com.mysql.jdbc.JDBC4Connection@2e5d6d97
        System.out.println(conn);

        //获取操作对象
        // Statement createStatement () 创建一个 Statement 对象来将 SQL 语句发送到数据库。

        //Statement 数据库的操作对象
        //java.sql 接口 Statement 用于执行静态 SQL 语句并返回它所生成结果的对象。
        Statement statement = conn.createStatement();
        //com.mysql.jdbc.StatementImpl@238e0d81
        System.out.println(statement);
        //使用操作对象,发送sql语句
        String sql = "insert into user values(null,'jdbc',password('123456'))";

        // ResultSet executeQuery (String sql)
        // 执行给定的 SQL 语句,该语句返回单个 ResultSet 对象。
        // int executeUpdate (String sql)
        // 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。

        //执行增删改的SQL语句,返回的是你影响的行数
        int i = statement.executeUpdate(sql);
        if (i > 0) {
            System.out.println("插入成功");
        } else {
            System.out.println("插入失败");
        }


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


3.使用JDBC查询数据,并封装到对象中

结果集对象ResultSet

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

Emp类:

import java.math.BigDecimal;
import java.util.Date;

//这个实体类----对应----数据中的 emp 表
//注意:实体类的成员变量名和数据类型,要和表中的列名以及数据类型保持一致。
public class Emp {
    private Integer empno;  //null
    private String ename;
    private String job;
    private Integer mgr;
    private Date hiredate;
    private BigDecimal sal;
    private BigDecimal comm;
    private Integer deptno;

    public Emp() {
    }

    public Emp(Integer empno, String ename, String job, Integer mgr, Date hiredate, BigDecimal sal, BigDecimal comm, Integer deptno) {
        this.empno = empno;
        this.ename = ename;
        this.job = job;
        this.mgr = mgr;
        this.hiredate = hiredate;
        this.sal = sal;
        this.comm = comm;
        this.deptno = 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 Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public BigDecimal getSal() {
        return sal;
    }

    public void setSal(BigDecimal sal) {
        this.sal = sal;
    }

    public BigDecimal getComm() {
        return comm;
    }

    public void setComm(BigDecimal 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 +
                '}';
    }
}

测试类:

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

public class MyTest {
    public static void main(String[] args) throws Exception {
        ArrayList<Emp> list = new ArrayList<>();
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydemodb", "root", "123456");
        Statement statement = conn.createStatement();
        String sql = "select * from emp";
        //执行查询操作,返回的是查询的结果集对象
        ResultSet resultSet = statement.executeQuery(sql);

        //遍历结果集对象,取出数据
        while (resultSet.next()) {
            int empno = resultSet.getInt("empno");
            String ename = resultSet.getString(2);
            String job = resultSet.getString("job");
            int mgr = resultSet.getInt("mgr");
            Date hiredate = resultSet.getDate("hiredate");
            BigDecimal sal = resultSet.getBigDecimal("sal");
            BigDecimal comm = resultSet.getBigDecimal("comm");
            int deptno = resultSet.getInt("deptno");

            System.out.println(empno);
            System.out.println(ename);
            System.out.println(job);
            System.out.println(mgr);
            System.out.println(hiredate);
            System.out.println(sal);
            System.out.println(comm);
            System.out.println(deptno);
            //注意查出的数据,要封装起来
            Emp emp = new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
            //把每个emp对象再放到集合中
            list.add(emp);

        }


        //System.out.println(list);
        for (Emp emp : list) {
            System.out.println(emp);
        }

        //释放资源

        conn.close();
        statement.close();
        resultSet.close();

    }
}


4.模拟登录(存在SQL注入风险)

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

public class MyTest {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的用名");
        String username = sc.nextLine();
        System.out.println("请输入你的密码");
        String password = sc.nextLine();

        //登录
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
        Statement statement = conn.createStatement();
        String sql = "select * from user where username='" + username + "' and password='" + password + "'";

        ResultSet resultSet = statement.executeQuery(sql);
        if (resultSet.next()) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }

        conn.close();
        statement.close();
        resultSet.close();


        //存在 SQL注入的风险

    }
}


5.使用预编译操作对象防止SQL注入

1. 代码层防止sql注入攻击的最佳方案就是sql预编译
2. 确认每种数据的类型,比如是数字,数据库则必须使用int类型来存储
3. 规定数据长度,能在一定程度上防止sql注入
4. 严格限制数据库权限,能最大程度减少sql注入的危害
5. 避免直接响应一些sql异常信息,sql发生异常后,自定义异常进行响应
6. 过滤参数中含有的一些数据库关键词

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

public class MyTest2 {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入你的用名");
        String username = sc.nextLine();
        System.out.println("请输入你的密码");
        String password = sc.nextLine();

        // String username = "1' or '1'='1";
        //  String password = "1' or '1'='1";


        //登录
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "123456");
        //为了防止SQL注入,我们使用预编译操作对象
        //Statement statement = conn.createStatement(); //不使用这个操作对象

        //注意:参数值,用?占位
        String sql = "select * from user where username=? and password=?";
        //PreparedStatement 预编译操作对象 可以防止SQL注入
        PreparedStatement preparedStatement = conn.prepareStatement(sql);
        //给问号赋值 问号编号从开始数
        preparedStatement.setString(1, username);
        preparedStatement.setString(2, password);

        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) {
            System.out.println("登录成功");
        } else {
            System.out.println("登录失败");
        }

        conn.close();
        preparedStatement.close();
        resultSet.close();


        //存在 SQL注入的风险
        //我们在Java程序中,如果拼接SQL语句就存在SQL注入的风险。

    }
}


6.编写JDBC工具类

JDBC工具类:

import java.sql.*;

public class JDBCUtils_old {

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

    private JDBCUtils_old() {

    }

    //耦合度太高,让程序和数据解耦,配合配置文件
    static {
        url = "jdbc:mysql://localhost:3306/mydb";
        username = "root";
        password = "123456";
        //登录
        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 conn, Statement statement, ResultSet resultSet) throws SQLException {
        if (conn != null) {
            conn.close();
        }
        if (statement != null) {
            statement.close();
        }
        if (resultSet != null) {
            resultSet.close();
        }

    }

    public static void close(Connection conn, Statement statement) throws SQLException {
        if (conn != null) {
            conn.close();
        }
        if (statement != null) {
            statement.close();
        }
    }
}

测试类:

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

public class MyTest {
    public static void main(String[] args) throws SQLException {
        Connection conn = JDBCUtils_old.getConnection();
        System.out.println(conn);

        PreparedStatement preparedStatement = conn.prepareStatement("select * from user");

        ResultSet resultSet = preparedStatement.executeQuery();

        JDBCUtils_old.close(conn, preparedStatement, resultSet);

    }
}

JDBCConfig.properties配置文件:

className=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb
username=root
password=123456

JDBC工具类:

import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;

public class JDBCUtils {

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

    private JDBCUtils() {

    }

    //耦合度太高,让程序和数据解耦,配合配置文件
    static {

        //登录
        try {
            Properties properties = new Properties();
            properties.load(new FileInputStream("JdbcConfig.properties"));
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            Class.forName(properties.getProperty("className"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接对象的方法

    public static Connection getConnection() throws SQLException {

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

        return conn;
    }

    //释放资源的方法

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

    }

    public static void close(Connection conn, Statement statement) throws SQLException {
        if (conn != null) {
            conn.close();
        }
        if (statement != null) {
            statement.close();
        }
    }
}

测试类:

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

public class MyTest {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        System.out.println(connection);
    }
}


7.批处理

 插入大量数据时,建议使用批处理来做
 statement.addBatch();//添加批处理,先将数据缓存起来
  statement.executeBatch();//执行批处理
  statement.clearBatch();//清空缓存

User类:

public class User {
    private Integer id;
    private String username;
    private String password;

    public User() {
    }

    public User(Integer id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

测试类:

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

public class MyTest {
    public static void main(String[] args) throws SQLException {
        ArrayList<User> list = new ArrayList<>();
        for (int i = 10; i <= 3000; i++) {
            User user = new User(i, "测试用户", "aaabbbbcccc");
            list.add(user);
        }

        Connection connection = JDBCUtils.getConnection();
        PreparedStatement preparedStatement = connection.prepareStatement("insert into user values (?,?,?)");
        for (User user : list) {
            preparedStatement.setInt(1, user.getId());
            preparedStatement.setString(2, user.getUsername());
            preparedStatement.setString(3, user.getPassword());
            //preparedStatement.executeUpdate();
            //添加批处理
            preparedStatement.addBatch();
        }

        //一次性执行
        preparedStatement.executeBatch(); //执行批处理

        //清空批处理
        preparedStatement.clearBatch();


        JDBCUtils.close(connection, preparedStatement);
    }
}


8.在Java程序中调用存储过程

import org.westos.demo6.JDBCUtils;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

public class MyTest {
    public static void main(String[] args) throws SQLException {
        //在Java程序中调用存储过程
        Connection conn = JDBCUtils.getConnection();
        String sql = "{call mydemo2(?,?)}"; //输入或输出参数用?占位
        //获取这个操作对象,来调用存储过程或者函数
        CallableStatement prepareCall = conn.prepareCall(sql);

        //给输入参数设置值
        prepareCall.setInt(1, 7782);

        //注册输出参数
        prepareCall.registerOutParameter(2, Types.INTEGER);

        //执行
        int i = prepareCall.executeUpdate();
        System.out.println(i);
        //获取输出参数的值
        if (i > 0) {
            int out = prepareCall.getInt(2);
            System.out.println(out);
        }
        //释放资源
        JDBCUtils.close(conn, prepareCall);

    }
}


9.Java中调用数据库的内置函数

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;

public class MyTest2 {
    public static void main(String[] args) throws SQLException {
        //Java中调用数据库的内置函数

        //在Java程序中调用存储过程
        Connection conn = JDBCUtils.getConnection();

        //第一个? 表示函数的返回值
        String sql = "{?=call md5(?)}";
        CallableStatement callableStatement = conn.prepareCall(sql);
        //设置输入参数
        callableStatement.setString(2, "123456");

        //注册返回值
        callableStatement.registerOutParameter(1, Types.VARCHAR);
        //执行
        callableStatement.execute();
        //获取返回的结果
        String r = callableStatement.getString(1);
        System.out.println("结果是:" + r);


        //释放资源
        JDBCUtils.close(conn, callableStatement);

    }
}


10.自增长键

import java.sql.*;

public class MyTest {
    public static void main(String[] args) throws SQLException {
        Connection conn = JDBCUtils.getConnection();
        //Statement.RETURN_GENERATED_KEYS 加上这个参数等会,可以获取你插入一条数据后,然后获取自增长键的值

        PreparedStatement preparedStatement = conn.prepareStatement("insert into user values (null,'aaa','bbbbbbbb')",
                Statement.RETURN_GENERATED_KEYS);

        int i = preparedStatement.executeUpdate();

        //获取自增长键的值
        ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
        while (generatedKeys.next()) {
            int id = generatedKeys.getInt(1);
            System.out.println(id);
        }


        JDBCUtils.close(conn, preparedStatement, generatedKeys);

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值