如何彻底卸载MySQL


内容为:

  1、控制面板里的增加删除程序内进行删除 

  2、删除MySQL文件夹

  3、开始->运行-> regedit 看看注册表里这几个地方删除没有 

  HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL 目录删除 

  HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL 目录删除 

  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL 目录删除(我卸载的时候没有找到,略过后仍达到完全卸载的目的。) 

  4、这一条是很关键的 

        C:\ProgramData\下有一个 mysql 目录 也要必须删除

      

  注意:AC:\ProgramData这个文件夹是隐藏的,需要打开个文件夹选择菜单栏 工具→文件夹选项→查看→隐藏文件和文件夹 一项选上 显示所有文件和文件夹 确定 

  以上4步完成,
    
    5.重启 OK!再次安装吧 
1. 你知道的存储数据的方式有哪些?
    变量, 常量, 数组, 集合:    
        它们只能临时存储数据, 当程序执行结束后, 数据就丢失了.
    IO流:
        可以实现对数据永久存储, 但是不方便用户进行精细化管理和操作. 
    数据库:
        数据库指的就是存储数据的仓库, 其本质是一个文件系统, 可以对数据有规律的存储,
        方便用户进行增删改查(CURD, Create: 增, Update: 改, Read: 读, Delete: 删).
        //记忆: 数据库才是实际开发, 我们真正存储数据的地方.
        
2. 我们常说的数据库其实指的是数据库管理系统(DBMS: DataBase Managerment System), 那么数据库和DBMS之间有什么关系呢?
    DBMS:        //类似于IDEA
    数据库:        //类似于IDEA中的项目
    数据表:        //类似于项目中的类.
    表数据:        //类似于通过类创建的JavaBean对象
        
3. 常用的DBMS有哪些?
    MySQL, Oracle, SQLServer, DB2, SQLite, SyBase.
    
4.     在window操作系统中安装MySQL
    卸载:    //友善提醒: 如果你的数据库需要备份, 卸载之前一定要先备份数据库.
        1. 直接去控制面板卸载, 不要直接删除mysql文件夹, 因为有注册表没有直接删除.
            //快速打开控制面板: window徽标键 + 字母r -> control -> 回车
        2. 删除MySQL文件夹.
        3. 如果你的操作系统不是纯净版的, 卸载后可能有些注册信息需要手动删除, 详见:  资料/如何彻底卸载mysql.txt
        
    安装:    //必须安装64位, 如果你的操作系统不是64位, 换系统.
        1. 傻瓜式安装, 双击安装包以后, 下一步下一步即可.
        2. 安装路径一定要合法:
            A. 安装路径不要出现中文, 空格, 特殊符号等. 
            B. 最好不要直接安装到盘符目录下. 
        3. 具体的安装动作详见:    MySQL安装图解.pdf
            
        细节: 安装之前最好关闭你电脑的防火墙, 有些电脑不管防火墙可能装不成功.
        
5. MySQL如何登陆和退出:
    登陆:
        方式一: 明文登陆
            window微标键 + 字母r -> cmd -> 回车 -> mysql -uroot -p密码 -> 回车
        
        方式二: 暗文登陆
            window微标键 + 字母r -> cmd -> 回车 -> mysql -u root -p -> 回车 -> 输入密码 -> 回车
        
    退出:
        exit
        quit
        
    登陆MySQL的时候可能会遇到的两个小问题:
        1. 10061, 看到这个错误码, 一定是你的 MySQL服务没有开启, 开启它即可.
            方式一: 手动开启
                window微标键 + 字母r -> cmd -> 回车 ->services.msc -> 找到 mysql 服务, 然后开.
            方式二:    DOS指令
                net start mysql服务名
        2. using password yes, 看到这个错, 说明你录入的用户名或者密码不对, 正确录入即可. 
            
6. JDBC简介
    概述:
        全称叫Java DataBase Connectivity(Java数据库连接), 就是通过Java语言来操作不同的数据库的技术, 本质就是一些类和接口.
        //DriverManager, Connection, Statement, PreparedStatement, ResultSet, Driver
        
        /*
            集合: 就是Java语言用来存储 多个同类型数据的容器, 本质就是一些类和接口.
                Collcetion, Set, List, Map, ArrayList, HashSet, HashMap
            IO流: 就是Java语言用来 进行文件传输的技术, 本质就是一些类和接口.
                InputStream, OutputStream, Reader, Writer, FileInputStream, BufferedInputStream, Serializable
            结论: 集合的顶层都是接口, IO流的顶层都是抽象类. 
        */
    作用:
        1. 连接数据库.
        2. 向数据库发送SQL语句.
        3. 接收数据库返回的执行结果, 并进行相应的处理. 
        
    驱动:
        就是两个设备间进行通信的桥梁.    //Java 和 MySQL之间进行交互, 也需要通过 驱动实现.
        //这里的驱动指的是: 数据库厂商提供的 jar包.
    
    原理:
        专业版:
            有Sun公司制定规则(就是一些类和接口), 具体的体现和实现交给: 各个数据库生产商来做. 
        大白话:
            我们知道, Java操作MySQL需要使用MySQL提供的驱动, Java操作SQLServer数据库, 需要使用SQLServer提供的驱动, 但是我们知道,
            数据库厂商不同, 提供的驱动也不尽相同, 这就要求Java程序员必须熟悉市场上常用的各个数据库的驱动的, 这样做会提高程序的
            学习门槛, 因为Java本身就已经提供了好多的类和接口, 此时程序员还需要额外记忆大量的其他的类和接口, 学习难度增大, 后来
            Sun公司就发现了这个问题, 于是就把各个数据库生厂商叫到一起进行协商, 决定: 由Sun公司提供统一的规则, 而具体的体现和
            实现交给各个数据库厂商来实现, 这些Sun公司提供统一的规则, 就是: JDBC, 本质就是一些类和接口.
        
7. JDBC的入门案例
    1. 准备数据库和数据表.
        #创建数据库
        create database day15;
        #使用数据库
        use day15;
        #创建分类表
        create table category(
            cid int PRIMARY KEY AUTO_INCREMENT ,
            cname varchar(20)
        );
        
    2. 添加表数据.              
        #初始化数据
        insert into category values(null, '家电');
        insert into category values(null, '服饰');
        insert into category values(null, '化妆品');
    
    3. 通过JDBC查询上述数据表中的所有数据, 并打印到控制台上.
        //需要先做的事儿: 导入驱动, 即: 导入MySQL数据库厂商提供的, 针对于MySQL数据库的jar包
        1. 注册驱动.
        2. 获取连接对象.
        3. 根据连接对象, 获取可以执行SQL语句的对象.
        4. 执行SQL语句, 获取结果集.
            //结果集: 就是SQL语句执行结束后, 返回的结果, 就叫: 结果集.
        5. 操作结果集.
        6. 释放资源. 
        
        
8. JDBC涉及的API简介之 DriverManager    
    概述:
        它是一个类 , 表示驱动管理者, 可以用来注册驱动 和 获取连接对象.
    作用:
        1. 注册驱动.
            public static void registerDriver(new Driver());
            /*
                上述注册驱动的方式, 会导致MySQL驱动注册两次, 所以我们通过反射的方式加载字节码文件, 这样的话 驱动只注册一次. 
                案例代码如下:
                    Class.forName("com.mysql.jdbc.Driver");
            */
        
        2. 获取连接对象. 
            public Connection getConnection(String url, String username, String password);
            /*
                参数解释:
                    参数1: 数据库连接字符串, 格式如下:
                        jdbc:mysql://要连接的MySQL的ip:3306/要操作的数据库的名字
                        
                        jdbc:mysql://localhost:3306/day15
                        jdbc:mysql://127.0.0.1:3306/day15
                        
                        如果操作本地数据库, 则上述的格式可以优化为: jdbc:mysql:///day15
                    
                    参数2: 要连接的数据库的账号
                    参数3: 要连接的数据库的密码
            */
        

9. JDBC涉及的API简介之 Connection    
    概述:
        它是一个接口, 表示: 连接对象(会话对象), 负责Java语言 和 数据库(例如:MySQL)之间交互的.
    作用:
        1. 获取可以执行SQL语句的对象.
            public Statement createStatement();                        
                //获取可以执行SQL语句的对象(Statement, 不具有预编译功能)
            public PreparedStatement prepareStatement(String sql);    
                //获取可以执行SQL语句的对象(PreparedStatement, 具有预编译功能)
        
        2. 可以操作事务.     //目前先了解.
            public void setAutoCommit(boolean flag);    //设置自动提交, 相当于开启/关闭事务.
            public void commit();        //提交事务
            public void rollback();        //事务回滚.
            public void setTransactionIsolation(int level);    //设置隔离级别.

10. JDBC涉及的API简介之 Statement    
    概述:
        它是接口, 具有执行SQL语句功能的对象, 可以执行SQL语句, 获取结果集.
    作用:
        1. 执行SQL语句, 获取结果.
            public ResultSet executeQuery(String sql);        //执行查询语句, 获取结果集.
            public int executeUpdate(String sql);            //执行更新语句(增删改), 获取结果集.
            
        2. 执行批处理.        //目前了解.
            public void addBatch();            //添加到批处理中
            public int[] executeBatch();    //执行批处理.
            public void clearBatch();        //清空批处理. 

11. JDBC涉及的API简介之 ResultSet
    概述:
        它是接口, 表示查询语句执行结束后, 返回的结果.
    
    作用:
        可以用来存储查询语句执行结束后, 返回的结果, 方便用户操作.
        
        public boolean next();        //判断结果集中是否有下一个元素.  类似于: Iterator#hasNext();
        
        public Xxx getXxx(String columnName);    //根据列名, 获取该列的值. Xxx表示数据类型.
        public Xxx getXxx(int columnNumber);    //根据列的编号, 获取该列的值, Xxx表示数据类型.
        
12. JDBC的CURD(增删改查)操作.
    1. 创建用户表users, 添加表数据.
        #创建用户表
        CREATE TABLE users(
            uid INT PRIMARY KEY AUTO_INCREMENT,
            username VARCHAR(20),
            PASSWORD VARCHAR(20)
        );
        #添加表数据
        INSERT INTO users VALUES(NULL, 'admin01', 'pw111');
        INSERT INTO users VALUES(NULL, 'admin02', 'pw222');
        INSERT INTO users VALUES(NULL, 'admin03', 'pw333');
        #查询表数据
        SELECT * FROM users;

    2. 通过JDBC操作users表, 进行CURD操作. 
        
13. JDBCUtils工具类的抽取和使用.
    略.
    
14. SQL注入攻击问题
    概述:
        实际开发中, 如果SQL语句的部分内容是要求用户录入的, 而用户录入某些非法字符或者我们所不希望看到的内容, 此时就有可能
        改变SQL语句的判断条件, 从而引发问题, 这种情况就叫做: SQL注入攻击问题. 
    问题演示:
        //示例: 模拟登陆的SQL语句.
        select * from users where username='用户录入的账号' and password='用户录入的密码';
        
        //此时用户录入的数据如下;
        用户录入的用户名:  sdlfjsldf
        用户录入的密码:       ' or '1=1            //此时就会发生SQL注入攻击问题.
        
    Java代码演示SQL注入攻击问题:
    
    SQL注入攻击问题解决: 预编译.
    
15. PreparedStatement预编译功能的CURD操作.

16. 数据库连接池
    概述:
        实际开发中, 当我们需要使用到大量生命周期短的连接对象时, 频繁的创建和销毁连接对象是非常消耗系统资源的,
        针对于这种情况, 我们可以创建一个池子出来, 里边放一些连接对象, 用的时候从里边拿, 用完之后在还回去. 
        这个池子就叫: 数据库连接池, 这样做的目的是: 节约资源, 提高效率.
    分类:
        DBCP: Apache提供的, 不能自动回收空闲连接. 
        C3P0: Apache提供的, 能自动回收空闲连接.         //只讲解这个.
            //Java框架的底层如果涉及到 数据库连接池部分的内容了, 基本上用的都是: C3P0数据库连接池.
        Druid: 阿里巴巴公司提供的, 采用 分布式事务思想实现.
    演示C3P0的使用:
        案例一: 入门案例.    
            步骤:
                1. 复制c3p0-config.xml配置文件到当前项目(模块)的src目录下.
                2. 导入c3p0数据库连接池的jar包.
                3. 创建数据库连接池对象, 无需关联和指定配置文件, 因为 C3P0数据库连接池会自动加载并识别配置文件的信息.
                4. 从数据库连接池对象中获取连接对象(Connection)
                5. 正常的 conn.close()关闭连接对象即可, 因为连接池已经重构了 Connection#close()方法, 
                   所以此时调用close()并不是 销毁连接对象, 而是 自动归还. 
            /*
                弊端: 
                    用连接池的效率还没有我们以前写的代码效率高.
                原因:
                    因为你是每执行一次这个类, 就创建一个连接池对象, 且要填充5个连接对象,但是在这个类中,
                    你才用到了1个连接对象, 剩下的4个连接对象都是闲置的, 这样做肯定不行, 那如何优化呢?
                解决方案:
                    把创建连接池对象的操作封装到工具类中, 然后在项目中需要用到连接池的地方, 直接给连接池对象即可,
                    只要保证整个项目(模块)共用一个连接池对象即可.
            */
            
        案例二: C3P0Utils工具类的抽取和使用
            
        
        
# **************************** 以下是演示 SQL注入攻击问题  **************************** 
/*
    SQL注入攻击问题:
        概述:
            用户录入非法字符, 从而改变了我们SQL语句的判断条件, 引发的安全问题, 就叫SQL注入攻击问题.
        示例(问题演示):
        需求:
            模拟用户登录.
        格式:
            select * from users where username='用户录入的账号' and password='用户录入的密码';
            
            普通用户:
                用户名:  admin01
                密码:     123
            屌丝用户:
                用户名:  sdlfjsldf
                密码:     ' or '1=1
            资深老屌丝:
                用户名:  sdlfjsldf
                密码:     ' or '1=1';drop database day15;'

                
*/

SELECT * FROM users WHERE username='sdlfjsldf' AND PASSWORD='' OR '1=1';DROP DATABASE day15;'';

jdbc操作MySQL

idea

1.创建一个Java项目

2.在项目下创建一个lib 或者libs文件夹存放驱动包

 

 3.将驱动包复制进去

 

 

 eclipse

同理创文件夹

复制包

 

 

package com.it.demo01_jdbc;

import com.mysql.jdbc.Driver;

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

/*
    案例: 演示JDBC操作数据库表, 入门.
 */
public class Demo01_QuickStart {
    public static void main(String[] args) throws Exception {
        //需要先做的事儿: 导入驱动, 即: 导入MySQL数据库厂商提供的, 针对于MySQL数据库的jar包
        //1. 注册驱动.
        //DriverManager.registerDriver(new Driver());   //这种方式会导致驱动注册两次, 改为通过反射实现.
        Class.forName("com.mysql.jdbc.Driver");       //这种方式只会注册一次驱动
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/day15", "root", "123456");
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();

        //4. 执行SQL语句, 获取结果集.
        ////结果集: 就是SQL语句执行结束后, 返回的结果, 就叫: 结果集.
        String sql = "SELECT * FROM category;";
        ResultSet rs = stat.executeQuery(sql);
        while (rs.next()) {  //判断是否还有下一个结果集.
            //从结果集在栈中获取数据.
            int cid = rs.getInt("cid");       //列名, 掌握
            //int cid = rs.getInt(1);             //列的编号, 了解
            String cname = rs.getString("cname");
            //5. 操作结果集.
            System.out.println("cid: "+ cid + ", cname: " + cname);
        }
        //6. 释放资源.
        rs.close();
        stat.close();
        conn.close();
    }
}

 

 

package com.it.demo01_jdbc;

import org.junit.Test;

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

/*
    案例: 操作day15数据库的 users表, 进行CURD操作.
 */
public class Demo02_CURD {
    /**
     * 演示JDBC之 查询数据
     */
    @Test
    public void read() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "select * from users;";
        ResultSet rs = stat.executeQuery(sql);
        //5. 操作结果集.
        while (rs.next()) {
            int uid = rs.getInt("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(uid + "..." + username + "..." + password);
        }
        //6. 释放资源.
        rs.close();
        stat.close();
        conn.close();
    }

    /**
     * 演示JDBC之 增加数据
     */
    @Test
    public void add() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "insert into users values(null, 'admin04', 'pw444');";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "添加成功" : "添加失败");
        //6. 释放资源.
        stat.close();
        conn.close();
    }

    /**
     * 演示JDBC之 修改数据
     */
    @Test
    public void update() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "update users set password='password444' where uid=4;";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "修改成功" : "修改失败");
        //6. 释放资源.
        stat.close();
        conn.close();
    }

    /**
     * 演示JDBC之 删除数据
     */
    @Test
    public void delete() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "delete from users where uid=4;";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "删除成功" : "删除失败");
        //6. 释放资源.
        stat.close();
        conn.close();
    }
}
package com.it.utils;

import java.sql.*;

/*
    案例: 自定义的针对于JDBC操作的工具类.
 */
public class JDBCUtils {
    //1. 构造方法私有化.
    private JDBCUtils() {
    }

    //2. 成员方法都是静态的.
    //3. 注册驱动, 在静态代码块中完成(执行特点: 随着类的加载而执行)
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //4. 对外提供一个获取连接对象的方法
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");
    }

    //5. 释放资源.
    //针对于查询语句
    public static void release(Connection conn, Statement stat, ResultSet rs) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;        //GC优先回收null对象.
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stat != null) {
                    stat.close();
                    stat = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (rs != null) {
                        rs.close();
                        rs = null;
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //针对于更新语句
    public static void release(Connection conn, Statement stat) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;        //GC优先回收null对象.
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stat != null) {
                    stat.close();
                    stat = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}




package com.it.demo01_jdbc;

import com.it.utils.JDBCUtils;
import org.junit.Test;

import javax.sql.rowset.JdbcRowSet;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

/*
    案例: 操作day15数据库的 users表, 进行CURD操作, 使用自定义的JDBCUtils工具类实现.
 */
public class Demo03_UseUtils {
    /**
     * 演示JDBC之 查询数据
     */
    @Test
    public void read() throws Exception {
        //1. 注册驱动.
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "select * from users;";
        ResultSet rs = stat.executeQuery(sql);
        //5. 操作结果集.
        while (rs.next()) {
            int uid = rs.getInt("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(uid + "..." + username + "..." + password);
        }
        //6. 释放资源.
        JDBCUtils.release(conn, stat, rs);
    }

    /**
     * 演示JDBC之 增加数据
     */
    @Test
    public void add() throws Exception {
        //1. 注册驱动.
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "insert into users values(null, 'admin04', 'pw444');";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "添加成功" : "添加失败");
        //6. 释放资源.
        JDBCUtils.release(conn, stat);
    }

    /**
     * 演示JDBC之 修改数据
     */
    @Test
    public void update() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "update users set password='password444' where uid=4;";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "修改成功" : "修改失败");
        //6. 释放资源.
        JDBCUtils.release(conn, stat);
    }

    /**
     * 演示JDBC之 删除数据
     */
    @Test
    public void delete() throws Exception {
        //1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "delete from users where uid=4;";
        int num = stat.executeUpdate(sql);
        //5. 操作结果集.
        System.out.println(num > 0 ? "删除成功" : "删除失败");
        //6. 释放资源.
        JDBCUtils.release(conn, stat);
    }
}
package com.ith.demo01_jdbc;

import com.it.utils.JDBCUtils;

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

/*
    案例: 演示SQL注入攻击问题.

    需求:
        提示用户录入他/她的用户名或者密码, 然后查询数据库, 判断用户是否登录成功, 并提示.
 */
public class Demo04_SQL注入攻击 {
    public static void main(String[] args) throws Exception {
        //1. 提示用户录入他/她的用户名或者密码, 并接收.
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入您的账号: ");
        String username = sc.nextLine();
        System.out.println("请录入您的密码: ");
        String password = sc.nextLine();

        //以下是标准的 JDBC代码
        //2. 注册驱动.
        //3. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //4. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //5. 执行SQL语句, 获取结果集.
        String sql = "select * from users where username='" + username + "' and password='" + password + "';";
        ResultSet rs = stat.executeQuery(sql);
        //6. 操作结果集.
        System.out.println(rs.next() ? "登录成功" : "登录失败, 用户名或者密码错误!");
        //7. 释放资源.
        JDBCUtils.release(conn, stat, rs);


    }
}
package com.itdemo01_jdbc;

import com.it.utils.JDBCUtils;

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

/*
    案例: 演示SQL注入攻击问题.

    需求:
        提示用户录入他/她的用户名或者密码, 然后查询数据库, 判断用户是否登录成功, 并提示.

    SQL注入攻击产生原因:
        因为用户录入的非法字符, 被我们的SQL语句识别为关键字或者特殊符号了, 导致我们的SQL语句的判断条件发生变化.

    解决方案:
        核心思想: 不管用户录入什么内容, 我们都当做普通字符处理.
        具体思路:
            就是采用预编译思想, 即: 预先对SQL语句进行编译, 把需要用户录入的地方用占位符填充, 此时就已经确定好了
            SQL语句的格式, 不管之后在传入什么内容, 我们都当做普通字符处理.
        涉及到的成员方法:
            Connection接口中的成员方法:
                public PreparedStatement prepareStatement(String sql);
                //获取可以执行SQL语句的对象(PreparedStatement, 具有预编译功能)
            PreparedStatement 是Statement接口的子类, 用法和Statement基本一致, 只不过有预编译功能.

 */
public class Demo05_SQL注入攻击_问题解决 {
    public static void main(String[] args) throws Exception {
        //1. 提示用户录入他/她的用户名或者密码, 并接收.
        Scanner sc = new Scanner(System.in);
        System.out.println("请录入您的账号: ");
        String username = sc.nextLine();
        System.out.println("请录入您的密码: ");
        String password = sc.nextLine();

        //以下是标准的 JDBC代码
        //2. 注册驱动.
        //3. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //4. 根据连接对象, 获取可以执行SQL语句的对象.
        //在这一步, 已经确定好了SQL语句的格式, 之后不管传入什么内容, 都会只当做普通字符处理.
        String sql = "select * from users where username=? and password=?;";
        PreparedStatement ps = conn.prepareStatement(sql);

        //给占位符填充值.
        ps.setString(1, username);          //占位符的索引从1开始.
        ps.setString(2, password);

        //5. 执行SQL语句, 获取结果集.
        ResultSet rs = ps.executeQuery();       //因为SQL语句已经进行了预编译, 且被ps对象所记录, 所以在执行SQL语句时, 无需在传入SQL语句了.
        //6. 操作结果集.
        System.out.println(rs.next() ? "登录成功" : "登录失败, 用户名或者密码错误!");
        //7. 释放资源.
        JDBCUtils.release(conn, ps, rs);


    }
}
package com.it.demo01_jdbc;

import com.it.utils.JDBCUtils;
import org.junit.Test;

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

/*
    案例: 演示采用预编译功能(即: PreparedStatement)完成 CURD操作.
 */
public class Demo06_PreparedStatement_CURD {
    //
    @Test
    public void read() throws Exception{
        //需求: 获取day15数据库users数据表的, 密码为 pw222的这条数据.
        //1. 注册驱动.
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        String sql = "select * from users where password = ? ;";
        PreparedStatement ps = conn.prepareStatement(sql);

        //给占位符设置值, 细节
        ps.setString(1, "pw222");

        //4. 执行SQL语句, 获取结果集.
        ResultSet rs = ps.executeQuery();
        //5. 操作结果集.
        if (rs.next()) {
            System.out.println(rs.getInt("uid") + "..." + rs.getString("username") + "..." +rs.getString("password"));
        }
        //6. 释放资源.
        rs.close();
        ps.close();
        conn.close();
    }

    //
    @Test
    public void add() throws Exception{
        //需求: 往day15数据库users数据表中添加数据, admin04, pw444
        //1. 注册驱动.
        //2. 获取连接对象.
        Connection conn = JDBCUtils.getConnection();
        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        String sql = "insert into users values(null, ?, ?);";
        PreparedStatement ps = conn.prepareStatement(sql);

        //给占位符设置值, 细节
        ps.setString(1, "admin04");
        ps.setString(2, "pw444");

        //4. 执行SQL语句, 获取结果集.
        int num = ps.executeUpdate();

        //5. 操作结果集.
        System.out.println(num > 0 ? "添加成功" : "添加失败");

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

    //删,

    //改,
}
package com.it.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

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

//抽取的 针对于C3P0数据库连接池操作的 工具类.
public class C3P0Utils {
    //1. 构造方法私有化.
    private C3P0Utils() {
    }

    //2. 创建数据库连接池对象, 要用static修饰, 保证大家使用同一个连接池对象.
    private static final ComboPooledDataSource cpds = new ComboPooledDataSource();

    //3. 定义方法, 对外提供获取 连接池对象.
    //数据库连接池的顶层接口是:  DataSource
    public static DataSource getDataSource() {
        return cpds;
    }

    //4. 定义方法, 对外提供获取 连接对象.
    public static Connection getConnection() throws Exception{
        return cpds.getConnection();
    }

    //5. 释放资源.
    //针对于查询语句
    public static void release(Connection conn, Statement stat, ResultSet rs) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;        //GC优先回收null对象.
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stat != null) {
                    stat.close();
                    stat = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (rs != null) {
                        rs.close();
                        rs = null;
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //针对于更新语句
    public static void release(Connection conn, Statement stat) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;        //GC优先回收null对象.
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stat != null) {
                    stat.close();
                    stat = null;
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}



package com.it.demo02_c3p0;

import com.it.utils.JDBCUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

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

/*
    案例: 演示C3P0数据库连接池入门内容.

    步骤:
        1. 复制c3p0-config.xml配置文件到当前项目(模块)的src目录下.
        2. 导入c3p0-config.xml的jar包.
        3. 创建数据库连接池对象, 无需关联和指定配置文件, 因为 C3P0数据库连接池会自动加载并识别配置文件的信息.
        4. 从数据库连接池对象中获取连接对象(Connection)
        5. 正常的 conn.close()关闭连接对象即可, 因为连接池已经重构了 Connection#close()方法,
           所以此时调用close()并不是 销毁连接对象, 而是 自动归还.

    弊端:
        我们写的这个代码, 效率比以前的代码效率还要低, 因为你是每执行一次这个类, 就创建一个连接池对象, 且要填充5个连接对象,
        但是在这个类中, 你才用到了1个连接对象, 剩下的4个连接对象都是闲置的, 这样做肯定不行, 那如何优化呢?
    解决方案:
        把创建连接池对象的操作封装到工具类中, 然后在项目中需要用到连接池的地方, 直接给连接池对象即可,
        只要保证整个项目(模块)共用一个连接池对象即可.

 */
public class Demo01 {
    public static void main(String[] args) throws Exception{
        //获取连接对象的方式一: 自己造.
        /*//1. 注册驱动.
        Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接对象.
        Connection conn = DriverManager.getConnection("jdbc:mysql:///day15", "root", "123");*/

        //获取连接对象的方式二: 通过自定义的工具类实现.
        //获取连接对象.
        //Connection conn = JDBCUtils.getConnection();

        //获取连接对象的方式三: 从数据库连接池中获取.
        //1. 创建数据库连接池对象.
        //该对象会去你当前项目下的src目录下查找: c3p0-config.xml文件, 并自动加载.
        ComboPooledDataSource cpds = new ComboPooledDataSource();                   //读取default-config标签中的配置信息.
        //ComboPooledDataSource cpds = new ComboPooledDataSource("otherc3p0");      //读取name属性为: otherc3p0 这组标签的配置.

        //2. 从数据库连接池中, 获取连接对象.
        Connection conn = cpds.getConnection();

        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "select * from users;";
        ResultSet rs = stat.executeQuery(sql);
        //5. 操作结果集.
        while (rs.next()) {
            int uid = rs.getInt("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(uid + "..." + username + "..." + password);
        }
        //6. 释放资源.
        rs.close();
        stat.close();
        conn.close();
        /*
            如果conn连接对象是我们直接创建的, 调用close()方法时, 就是: 销毁conn对象.
            如果conn对象是从数据库连接池中获取的, 调用close()方法是, 就是自动归还此对象到: 连接池中,
            因为连接池已经把 Connection#close()的机制给重写了, 将其从 "销毁" 变为 "自动归还".
         */
    }
}





package com.it.demo02_c3p0;

import com.it.utils.C3P0Utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

/*
    案例: 演示 C3P0Utils工具类的使用.
 */
public class Demo02 {
    public static void main(String[] args) throws Exception {
        //思路一: 先获取连接池, 然后在获取连接对象.
        //DataSource ds = C3P0Utils.getDataSource();      //获取连接池
        //Connection conn = ds.getConnection();           //从连接池中获取 连接对象

        //思路二: 直接获取连接对象.
        Connection conn = C3P0Utils.getConnection();

        //3. 根据连接对象, 获取可以执行SQL语句的对象.
        Statement stat = conn.createStatement();
        //4. 执行SQL语句, 获取结果集.
        String sql = "select * from users;";
        ResultSet rs = stat.executeQuery(sql);
        //5. 操作结果集.
        while (rs.next()) {
            int uid = rs.getInt("uid");
            String username = rs.getString("username");
            String password = rs.getString("password");
            System.out.println(uid + "..." + username + "..." + password);
        }
        //6. 释放资源.
       C3P0Utils.release(conn, stat, rs);
    }
}

 

posted on 2021-02-03 16:53  王平  阅读(70)  评论(0)    收藏  举报