JDBC快速入门(带小案例)

JDBC快速入门

文章目录

  • JDBC快速入门
    • 步骤
    • API详解
      • 一,DriverManager
      • 二,Connection
        • 获取执行sql对象
        • JDBC事务管理
      • 三,Statement
      • 四,ResultSet
        • ResultSet小案例
      • 五,PreparedStatement
        • 1.PreparedStatment原理
        • 2.用户登录小案例
        • 3. sql注入小案例
        • 4. 解决sql注入问题的小案例

步骤

  1. 创建工程,导入jar包,下载网址:https://downloads.mysql.com/archives/c-j/

  2. 注册驱动

    Class.forName("com.mysql.jdbc.Driver");
    
  3. 获取连接

    Connection conn = DriverManager.getConnection(url.username,password);
    
  4. 定义sql语句

    String sql ="update..."
    
  5. 获取sql对象

    Statement stmt = conn.createStatement();
    
  6. 执行sql

    stmt.executeUPdate(sql);
    
  7. 处理返回结果

  8. 释放资源

  9. 代码

package com.itlyc.jdbc;

import com.mysql.jdbc.Driver;

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

/**
 * 玥骋
 * JDBC 快速入门
 */

public class JBDCdemo {
    public static void main(String[] args) throws Exception {

        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义sql
        String sql = "update dept set dname='李玥骋' where did=2";

        //4.获取执行sql的对象statement
        Statement state = conn.createStatement();


        //5.执行sql
        int i = state.executeUpdate(sql);//返回受影响的行数

        //6.处理结果
        System.out.println(i+"行受到影响");

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

API详解

一,DriverManager

  • DriverManager (驱动管理类)作用:
  1. 注册驱动

    • Driver类源码

      package com.mysql.jdbc;
      
      import java.sql.DriverManager;
      import java.sql.SQLException;
      
      public class Driver extends NonRegisteringDriver implements java.sql.Driver {
          public Driver() throws SQLException {
          }
      
          static {
              try {
                  //我们可以看到注册驱动的方法就在Driver类的静态方法中,随着类的加载被加载
                  DriverManager.registerDriver(new Driver());
              } catch (SQLException var1) {
                  throw new RuntimeException("Can't register driver!");
              }
          }
      }
      
      
  2. 获取数据库连接

static Connection     getConnection(String url , String user , String password)
  • 参数:

    1. url连接路径
    2. user :用户名
    3. password:密码
    语法:jdbc:mysql://ip地址(域名):端口号/数据库名称?键值对1&键值对2...
    
    例子:  jdbc:mysql://127.0.0.1:3306/db01
    
    注:如果连接的本地MySQL 并且端口号默认为3306的话可以简化书写
        jdbc:mysql:///数据库名称
    

二,Connection

获取执行sql对象
  • 普通执行sql对象:Statement createStatement()
  • 预编译sql的执行sql对象:防止sql注入 :PreparedStatement prepareStatement(sql)
  • 执行存储过程对象:Callable Statement prepareCall(sql)
JDBC事务管理

Connection接口中定义了三个对应的方法

  • 开启事务:setAutoCommit(boolean autoCommit):true为自动提交事务,false为手动提交事务,也就是开启事务
  • 提交事务:commit()
  • 回滚事务:roollback()

例子:

package com.itlyc.jdbc;

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

/**
 * 玥骋
 * JDBC API详解
 */

public class JBDCdemo_Connection {
    public static void main(String[] args) throws Exception {

        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义sql
        String sql1 = "update dept set dname='李玥骋' where did=2";
        String sql2 = "update dept set dname='肖婉茹' where did=3";

        //4.获取执行sql的对象statement
        Statement stmt = conn.createStatement();


        try {
            //开启事物
            conn.setAutoCommit(false);
            //5.执行sql
            int i1 = stmt.executeUpdate(sql1);//返回受影响的行数
            //6.处理结果
            System.out.println(i1+"行受到影响");

            //5.执行sql
            int i2= stmt.executeUpdate(sql2);//返回受影响的行数
            //6.处理结果
            System.out.println(i2+"行受到影响");

            //提交事物
            conn.commit();
        } catch (SQLException e) {
            //回滚事物
            conn.rollback();
            e.printStackTrace();
        }

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

  • 使用 try/catch来操作事务,可以在事务中发生异常时回滚事务
package com.itlyc.jdbc;

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

/**
 * 玥骋
 * JDBC API详解
 */

public class JBDCdemo_Connection {
    public static void main(String[] args) throws Exception {

        //1.注册驱动
        //Class.forName("com.mysql.jdbc.Driver");

        //2.获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);

        //3.定义sql
        String sql1 = "update dept set dname='码云' where did=2";
        String sql2 = "update dept set dname='麻花' where did=3";

        //4.获取执行sql的对象statement
        Statement stmt = conn.createStatement();


        try {
            //开启事物
            conn.setAutoCommit(false);
            //5.执行sql
            int i1 = stmt.executeUpdate(sql1);//返回受影响的行数
            //6.处理结果
            System.out.println(i1+"行受到影响");

            //主动造一个异常,try捕获到异常,下方catch会进行处理,调用rollback()方法来回滚事务
            int i = 3/0;

            //5.执行sql
            int i2= stmt.executeUpdate(sql2);//返回受影响的行数
            //6.处理结果
            System.out.println(i2+"行受到影响");

            //提交事物
            conn.commit();
        } catch (Exception e) {
            //回滚事物,
            conn.rollback();
            e.printStackTrace();
        }

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

三,Statement

  • Statment作用:执行SQL语句
  • int executeUpdate :执行DML,DDL语句
    1. 返回值为int类型,返回的是dml语句影响的行数
    2. 但是DDL语句执行成功也也能返回0
  • ResultSet executeQuery(SQL) :执行DQL
  • 语句
    1. 返回值为ResultSet对象

例:

  • DML
package com.itlyc.jdbc;

import org.junit.jupiter.api.Test;

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

/**
 * 玥骋
 * JDBC 执行DML语句
 */

public class JBDCdemo_Statement {
    @Test
    public void testDML() throws Exception {
            //1.注册驱动
            //Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/db01";
            String username = "root";
            String password = "lyc";
            Connection conn = DriverManager.getConnection(url, username, password);
            //3.定义sql
            String sql = "update dept set dname='jack' where did=1";
            //4.获取执行sql的对象statement
            Statement stmt = conn.createStatement();
            //5.执行sql
            int i = stmt.executeUpdate(sql);//执行完DMLsql后的返回值为受影响的行数
            //6.处理结果
            if (i>0){
                System.out.println(i+"行受到影响,执行成功!");
            }else{
                System.out.println(i+"行受到影响,执行失败!");
            }
            //7.释放资源
            stmt.close();
            conn.close();
    }
}

  • DDL
/**
 * 玥骋
 * JDBC 执行dml语句
 */

public class JBDCdemo_Statement {
    @Test
    public void testDDL() throws Exception {
            //1.注册驱动
            //Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/db01";
            String username = "root";
            String password = "lyc";
            Connection conn = DriverManager.getConnection(url, username, password);
            //3.定义sql
            String sql = "DROP database db02";//删除数据库db02
            //4.获取执行sql的对象statement
            Statement stmt = conn.createStatement();
            //5.执行sql
            int i = stmt.executeUpdate(sql);//执行完DDLsql后的返回值为受影响的行数
            System.out.println(i);
            //7.释放资源
            stmt.close();
            conn.close();
    }
}

四,ResultSet

  • ResultSet(结果集对象)作用:

    1. 封装了DQL查询语句的结果

      ResultSet stmt.executeQuery(SQL):执行DQL语句返回ResultSet对象
      
  • 获取查询结果

    boolean next():  1.将光标从当前位置向下移动一行
    				 2. 判断当前行是否为有效行
    返回值:
    true:有效行,当前行有数据
    false:无效行,当前行没有数据
    
    xxx  getXxx(参数):获取数据
    1.xxx 数据类型 如:int  getint(参数)String getString(参数)2.参数
    int:列的编号从1开始
    String:列的名称
    
  • 使用方法与步骤

    1.游标向下移动一行,并判断改行是否有数据:next()

    2.获取数据:getXxx(参数)

    //循环判断游标是否为数据的最后一行末尾
    while(rs.next){
    //获取数据
    rs.getXxx(参数);
    }
    
  • /**
     * 玥骋
     * JDBC 执行DQL语句
     *ResultSet的基础用法
     */
    
    public class JBDCdemo_ResuletSet {
        @Test
        public void testDQL() throws Exception {
                //1.注册驱动
                //Class.forName("com.mysql.jdbc.Driver");
                //2.获取连接
                String url = "jdbc:mysql://127.0.0.1:3306/db01";
                String username = "root";
                String password = "lyc";
                Connection conn = DriverManager.getConnection(url, username, password);
                //3.定义sql
                String sql = "SELECT*FROM dept";
                //4.获取执行sql的对象statement
                Statement stmt = conn.createStatement();
                //5.执行sql
                ResultSet rs = stmt.executeQuery(sql);//执行完DMLsql后的返回值为受影响的行数
                //6.处理结果,遍历rs中的数据
                while(rs.next()){
                    int did = rs.getInt("did");
                    String dname = rs.getString("dname");
    
                    System.out.println(did);
                    System.out.println(dname);
                    System.out.println("---------------------------------");
                }
                //7.释放资源
                rs.close();
                stmt.close();
                conn.close();
        }
    }
    
    ResultSet小案例
    • 查询account账户数据表,封装为Account对象中,并且存储到Arraylist集合中
    /**
         * 案例
         * 查询account账户数据表,封装为Account对象中,并且存储到Arraylist集合中
         * 1.定义实体类Acctount
         * 2.查询数据,封装到Account对象中
         * 3.将account对象存入Arraylist集合中
         * @throws Exception
         */
    
        @Test
        public void testResultSet1() throws Exception {
            //1.注册驱动
            //Class.forName("com.mysql.jdbc.Driver");
            //2.获取连接
            String url = "jdbc:mysql://127.0.0.1:3306/db01";
            String username = "root";
            String password = "lyc";
            Connection conn = DriverManager.getConnection(url, username, password);
            //3.定义sql
            String sql = "SELECT*FROM dept";
            //4.获取执行sql的对象stmt
            Statement stmt = conn.createStatement();
            //5.执行sql
            ResultSet rs = stmt.executeQuery(sql);//执行完DMLsql后的返回值为受影响的行数
            //new集合
            ArrayList<Account> arrayList = new ArrayList<>();
            //6.处理结果,遍历rs中的数据
            while(rs.next()){
                Account account = new Account();
                //获取数据
                int did = rs.getInt("did");
                String dname = rs.getString("dname");
    
                //赋值
                account.setId(did);
                account.setName(dname);
    
                //存入集合
                arrayList.add(account);
            }
            System.out.println(arrayList);
            //7.释放资源
            rs.close();
            stmt.close();
            conn.close();
        }
    
    package com.itlyc.opjo;
    //Account类
    public class Account {
        int id;
        String 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;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    

五,PreparedStatement

1.PreparedStatment原理
  • 在获取PreparedStatment对象时,将sql语句发给mysql服务器进行检查,编译,(因为这部耗时)

  • 执行时就不需要进行耗时的步骤,速度很快

  • 如果sql模板一样,则只需要进行一次检查编译,大大节省时间

  • 开启预编译

    //因为预编译功能默认关闭,所以我们需要手动打开:useServerPrepStmts=true
    String url = "jdbc:mysql://127.0.0.1:3306/db01?useServerPrepStmts=true";
    
    sql日志文件
    2022-03-26T06:19:26.610868Z	  4 Prepare	select * from dept where did=? and dname=?
    2022-03-26T06:19:26.610868Z	  4 Execute	select * from dept where did='1' and dname='\' or \'1\'=\'1'  # 注此处将敏感字符转义(' or '1'='1)
    2022-03-26T06:19:26.611865Z	  4 Close stmt	
    2022-03-26T06:19:26.611865Z	  4 Quit	
    
  • 作用:预编译sql语句并执行,预防SQL注入问题,将敏感字符转义并且预编译性能更高

  • SQL语句已预编译并存储在preparedStatment对象中,然后,可以使用此对象多次有效的执行此语句。

2.用户登录小案例
/**
 * 玥骋
 * JDBC 用户登录小案例
 */
@Test
    public void testlogin() throws Exception {
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);

        //接收用户名和密码
        String name ="2";
        String pswd ="jack";
        String sql = "select * from dept where did='"+name+"' and dname='"+pswd+"'";
        //获取stmt对象
        Statement stmt = conn.createStatement();
        //执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //判断登录是否成功
        if (rs.next()){
            System.out.println("登陆成功~");
        }else{
            System.out.println("登录失败~");
        }
        rs.close();
        stmt.close();
        conn.close();
    }
3. sql注入小案例
  • SQL注入:SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。
@Test
    /**
     * 玥骋
     * JDBC 用户登录小案例
     */
    public void testlogin_Inject() throws Exception {
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);

        //接收用户名和密码
        String name ="4";
        String pswd ="' or '1'='1";
        String sql = "select * from dept where did='"+name+"' and dname='"+pswd+"'";
        System.out.println(sql);
        //获取stmt对象
        Statement stmt = conn.createStatement();
        //执行sql
        ResultSet rs = stmt.executeQuery(sql);

        //判断登录是否成功
        if (rs.next()){
            System.out.println("登陆成功~");
        }else{
            System.out.println("登录失败~");
        }
        rs.close();
        stmt.close();
        conn.close();
    }
//我们写的sql就变成了该式子,因为and比or先执行false or true,使整个sql语句变为true,所以查询成功,登陆成功
select * from dept where did='4' and dname='' or '1'='1'
登陆成功~
4. 解决sql注入问题的小案例

为了解决sql注入问题 我们可以使用PrepareStatement

步骤:

  1. 获取PrepareStatment对象

    //SQL语句中的参数值,使用?占位符替代
    String sql="select * from user where username = ? and passsworld = ?";
    
    //通过Connection 对象获取,并传入对应的sql语句
    PreparedStatement pstmt = conn.prepareStatement(sql);
    
  2. 设置参数值

    PreparedStatement 对象:setXxx(参数1,参数2:?赋值
    
    注:Xxx:数据类型;setInt(参数1,参数2);
       参数:参数1: ?的位置编号,从1开始,对应sql语句中的? 位置
       		参数2: ?的值,对应sql语句中的? 位置
    
  3. 执行sql

    executeUpdate(); / executeQuery();
    不在需要传递sql
    

    防止sql注入案例

@Test
    /**
     * 玥骋
     * JDBC 防止sql注入小案例
     */
    public void testlogin_In() throws Exception {
        String url = "jdbc:mysql://127.0.0.1:3306/db01";
        String username = "root";
        String password = "lyc";
        Connection conn = DriverManager.getConnection(url, username, password);
        //接收用户名和密码
        String name ="1";
        String pswd ="' or '1'='1";//sql注入

        String sql = "select * from dept where did=? and dname=?";//用?占位符代替我们的值

        //获取pstmt对象,并把sql传入prepareStatement对象中
        PreparedStatement pstmt = conn.prepareStatement(sql);

        //设置  ?  的值
        pstmt.setString(1,name);
        pstmt.setString(2,pswd);

        //执行sql
        ResultSet rs = pstmt.executeQuery();

        //判断登录是否成功
        if (rs.next()){
            System.out.println("登陆成功~");
        }else{
            System.out.println("登录失败~");
        }
        rs.close();
        pstmt.close();
        conn.close();
    }

你可能感兴趣的:(JavaWeb,java,mysql,SQL注入)