JDBC(入门,ResultSet,SQL注入,批处理,调用存储过程和函数,获取自增长键的值)

1、概述

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

2、使用JDBC

(1)入门
/*1.导入数据库的驱动jar包,mysql版本不同jar包不同
2.加载驱动jar包
3.获取连接对象
4. 获取操作对象
5.开始操作
6.释放资源*/
public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
       //MySQL 8.0版本
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url="jdbc:mysql://localhost:3306/mytest1?serverTimezone=UTC";
       //MySQL 5.0版本
        Class.forName("com.mysql.jdbc.Driver");//可以省略不写
        String url="jdbc:mysql://localhost:3306/mytest1";
        String username="root";
        String password="123456";
        Connection conn = DriverManager.getConnection(url, username, password);
        Statement statement = conn.createStatement();
        String sql="insert into users values('wangwu','123456')";
        int i = statement.executeUpdate(sql); //返回值是影响的行数
        if(i>0){
            System.out.println("插入成功");
        }else{
            System.out.println("插入失败");
        }
        //6.释放资源
        conn.close();
        statement.close();
    }
}
(2)类的介绍
  • class.forName((“com.mysql.cj.jdbc.Driver”);加载驱动,也可以省略不写。
package com.mysql.cj.jdbc;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    public Driver() throws SQLException {
    }
    //查看源码可知 注册驱动这个操作是静态代码块来实现
    static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }
}
  • 类 DriverManager Java提供的 管理一组 JDBC 驱动程序的基本服务。
  • 接口 Connection 试图建立到给定数据库 URL 的连接。
  • 接口 Statement 用于执行静态 SQL 语句并返回它所生成结果的对象。
statement.execute(sql);//用来执行所有的SQL语句,如果第一个结果为 ResultSet 对象,则返回 true;如果
 //其为更新计数或者不存在任何结果,则返回 false 
statement.executeUpdate(sql);//用来执行DML语句 用来对表中数据进行增删改 返回值是影响的行数
statement.executeQuery(sql);//用来执行DQl语句 用来对表中数据进行查询
(3)结果集对象 ResultSet
  • 概念:结果集对象,是我们执行了查询语句之后返回的一个查询结果对象。
  • 用法:ResultSet对象具有指向其当前数据行的光标,最初光标被置于第一行之前,next方法将光标移动到下一行,在没有下一行时返回false,所以可以使用它来迭代结果集。
package com.westo.jdbc2;
import java.sql.*;
public class Demo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mytest1?serverTimezone=UTC", "root", "123456");
       String sql=" select *from user";
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);
        while (resultSet.next()) {
            String username = resultSet.getString("username");//参数可以是表的字段名 也可以是序号(从1开始)
            String password = resultSet.getString("password");
            System.out.println(username + "==" + password);
        }
        connection.close();
        statement.close();
        resultSet.close();
    }
}
(4)SQL注入问题

SQL注入:一些对数据库语法特别精通的人,可以利用一些数据库的语法规则,写出一些特殊sql的语句,来绕过数据库的验证。

package com.westo.jdbc2;
import java.sql.*;
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mytest1?serverTimezone=UTC", "root", "123456");
        Statement statement = connection.createStatement();
        //我们发现这样也可以登录成功 
        String username="1'or '1'='1";
        String password="1'or '1'='1";
        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("登录失败");
        }
        connection.close();
        statement.close();
        resultSet.close();
    }
}

PreparedStatement 预编译操作对象可以在安全方面防止SQL注入。

使用步骤

  • conn.prepareStatement(sql);
  • sql语句中的字段的值用?问号占位
  • 给sql语句中的问号赋值
package com.westo.jdbc2;
import java.sql.*;
public class Demo1 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mytest1?serverTimezone=UTC", "root", "123456");
        String username="1'or '1'='1";
        String password="1'or '1'='1";
        //值用?号占位
        String sql="select *from user where username=? and password=?";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setString(1,username);
        preparedStatement.setString(2,password);
        ResultSet resultSet = preparedStatement.executeQuery();
        if (resultSet.next()) {
            System.out.println("登陆成功");
        }else{
            System.out.println("登录失败");
        }
        connection.close();
       preparedStatement.close();
       resultSet.close();
    }
}

3、JDBC操作

(1)JDBC工具类
package com.westo.jdbc2;
import java.io.FileReader;
import java.sql.*;
import java.util.Properties;
public class JDBCutils {
    private static String url;
    private static String username;
    private static String password;
    static{
        try {
            //将基本信息放在配置文件中 从文件中读取
            Properties properties = new Properties();
            properties.load(new FileReader("JDBC.properties"));
            Class.forName(properties.getProperty("classname")) ;
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接对象
    public static Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url, username, password);
        return connection;
    }
    //释放资源
    public static void close(Connection connection, Statement statement, ResultSet resultSet) throws SQLException {
        if (connection!=null) {
            connection.close();
        }
        if (statement!=null) {
            statement.close();
        }
        if (resultSet!=null) {
            resultSet.close();
        }
    public static void  close(Connection connection,Statement statement) throws SQLException {
        if (connection!=null) {
            connection.close();
        }
        if (statement!=null) {
            statement.close();
        }
    }
}
(2)批处理

插入大量数据时,建议使用批处理来做。

package com.westo.jdbc2;
import com.westo.utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
public class Demo3 {
    public static void main(String[] args) throws SQLException {
        //模拟插入大量数据
        ArrayList<User> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            User user1 = new User(i, "大量数据");
            list.add(user1);
        }
        Connection connection = JDBCUtils.getConnection();
        String sql="insert into user values(?,?)";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        for (User user : list) {
            //这种方式 没添加一条数据 executeUpdate执行一次
            preparedStatement.setInt(1,user.getId());
            preparedStatement.setString(2,user.getName());
            //preparedStatement.executeUpdate();
            //我们可以先把数据缓存起来
            preparedStatement.addBatch();
        }
        //统一一次执行
        preparedStatement.executeBatch();
        //清空批处理
        preparedStatement.clearBatch();
        JDBCUtils.close(connection,preparedStatement);
    }
}
class User{
    private int id;
    private String name;
    public User() { }
    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
(3)调用存储过程
// 存储过程
DELIMITER $$
USE `mytest1`$$
DROP PROCEDURE IF EXISTS `procedure2`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `procedure2`(IN num INT,OUT result INT)
BEGIN
        -- 定义一个局部变量
        DECLARE i INT DEFAULT 1;
        DECLARE sum1 INT DEFAULT 0;
        WHILE i<=num DO
            SET sum1=sum1+i;
            SET i=i+1;
        END WHILE;-- 结束循环
        SET result=sum1;
    END$$
DELIMITER ;
//java代码
package com.westo.jdbc2;
import com.westo.utils.JDBCUtils;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class Demo4 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        String sql="{call procedure2(?,?)}";//输入输出参数用?占位
        CallableStatement prepareCall = connection.prepareCall(sql);
        //给输入参数赋值
        prepareCall.setInt(1,100);
        //需要注册输出参数
        prepareCall.registerOutParameter(2, Types.INTEGER);
        prepareCall.execute();
        //获取输出结果
        int anInt = prepareCall.getInt(2);
        System.out.println(anInt);
        JDBCUtils.close(connection,prepareCall);
    }
}
(4)调用自定义函数
//函数
SET GLOBAL log_bin_trust_function_creators=TRUE;
DELIMITER $$
CREATE
    FUNCTION `mytest1`.`funct`(num INT)
    RETURNS INT
    BEGIN
    DECLARE i INT DEFAULT 100;
    SET i=i+num;
    RETURN i;
    END$$
DELIMITER; 
//java代码
package com.westo.jdbc2;
import com.westo.utils.JDBCUtils;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Types;
public class Demo5 {
    public static void main(String[] args) throws SQLException {
        //调用自定义函数
        Connection connection = JDBCUtils.getConnection();
        String sql="{?=call funct(?)}";
        CallableStatement callableStatement = connection.prepareCall(sql);
        //设置输入参数
        callableStatement.setInt(2,100);
        callableStatement.registerOutParameter(1, Types.INTEGER);
        callableStatement.execute();
        int anInt = callableStatement.getInt(1);
        System.out.println(anInt);
        JDBCUtils.close(connection,callableStatement);
    }
}
(5)获取自增长键的值

要获取自增长键的值,需要在获取操作对象时声明一个参数 Statement.RETURN_GENERATED_KEYS

package com.westo.jdbc2;
import com.westo.utils.JDBCUtils;
import java.sql.*;
public class Demo6 {
    public static void main(String[] args) throws SQLException {
        Connection connection = JDBCUtils.getConnection();
        String sql="insert into demo(username,password) values('张三','123456')";
        PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
        int i = preparedStatement.executeUpdate();
        if (i>0) {
            System.out.println("添加成功");
        }else{
            System.out.println("添加失败");
        }
        //获取自增长键的值 结果集
        ResultSet generatedKeys = preparedStatement.getGeneratedKeys();
        int anInt=0;
        while (generatedKeys.next()) {
            anInt = generatedKeys.getInt(1);
            System.out.println(anInt);
        }
    }
}
发布了60 篇原创文章 · 获赞 19 · 访问量 2565

猜你喜欢

转载自blog.csdn.net/weixin_44324174/article/details/105360671