【JDBC】笔记(3)-「终于解决」

【JDBC】笔记(3)-「终于解决」1.Statement 编译一次,只执行一次,PreparedStatement 编译一次,可执行n次,所以 PreparedStatement 效率较高……

【JDBC】笔记(3)-

一.实现功能:

    1.解决“应用Statement的登录系统”存在的SQL注入问题
    2.用户信息表
    +—-+———–+———-+———-+
    | id | loginName | loginPwd | realName |
    +—-+———–+———-+———-+
    |  1 | abc       | 123      | 张三     |
    |  2 | wwe       | 456      | 李四     |
    +—-+———–+———-+———-+

 

二.代码实现:

 

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

public class JDBCTest02 {
    public static void main(String[] args) {
        //初始化界面(用户输入账号和密码)
        Map<String,String> userLoginInfo = initUI();
        //验证用户名和密码(JDBC)
        boolean loginSuccess = login(userLoginInfo);
        //显示结果:
        System.out.println(loginSuccess==true?"登录成功":"登录失败");
    }

    /**
     * 验证用户登录信息是否正确
     * @param userLoginInfo 用户登录信息
     * @return false 表示登录失败,true 表示登录成功
     */
    private static boolean login(Map<String, String> userLoginInfo) {
        //打标记(登录结果)
        boolean loginSuccess = false;

        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        try {
            //1、注册驱动
            Class.forName("com.mysql.cj.jdbc.Driver");

            //2、获取连接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/bjpowernode",
                    "root","888");

            //3、获取预编译的数据库操作对象
            //一个?代表一个占位符,一个?接受一个“值”
            String sql = "select * from t_user where loginName = ? and loginPwd = ? ";
            //程序执行到此处,会发送sql语句框子给DBMS,然后DBMS进行sql的编译
            ps = connection.prepareStatement(sql);
            //给占位符传值(第一个?下标是1,第二个?下标是2,JDBC的的下标从1开始)
            ps.setString(1,userLoginInfo.get("loginName"));
            ps.setString(2,userLoginInfo.get("loginPwd"));

            //4、执行sql
            resultSet = ps.executeQuery();

            //5、处理结果集
            //不需要while结果集,因为查询结果不是 无 就是 1条记录
            if (resultSet.next()){
                loginSuccess = true;
            }

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            //从小到大分别关闭三个资源
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
        //最后返回 登录结果(boolean)
        return loginSuccess;
    }

    /**
     * 初始化用户界面
     * @return 用户的用户名和密码(Map)
     */
    private static Map<String, String> initUI() {
        Scanner s=new Scanner(System.in);

        System.out.println("用户名:");
        String loginName = s.nextLine();

        System.out.println("密码:");
        String loginPwd = s.nextLine();

        //用 HashMap(键值对的方式)存储用户输入的 账号和密码
        Map<String,String> userLoginInfo = new HashMap<>();
        userLoginInfo.put("loginName",loginName);
        userLoginInfo.put("loginPwd",loginPwd);

        return userLoginInfo;
    }
}

 

三.效果展示:

1.使用 PreparedStatement 解决了SQL注入问题:

用户名:
yyds
密码:
yyds" or "1"="1
登录失败

Process finished with exit code 0

2.注意:

1)JDBC代码部分的第三步 — 获取预编译的数据库操作对象(不同于Statement):

先写好sql语句模型:

String sql = "select * from t_user where loginName = ? and loginPwd = ? ";

发送sql语句框子给DBMS,然后DBMS准备进行sql的编译:

ps = connection.prepareStatement(sql);

给占位符传值:?的值为String就setString,?的值为int就setInt …

ps.setString(1,userLoginInfo.get("loginName"));
ps.setString(2,userLoginInfo.get("loginPwd"));

 

四.Statement 与 PreparedStatement 对比:

1.Statement 编译一次执行一次,PreparedStatement 编译一次,可执行n次,所以 PreparedStatement 效率较高;

2.PreparedStatement 比 Statement 更加安全;

3.Statement 可以完成根据用户的意愿,通过输入sql语句来实现相应的功能,比如:升序(asc)/降序(desc):

1)假设使用 PreparedStatement:

用户想通过按“账号首字母”升序的方式看到用户的信息,所以向?传入“asc”,但这样运行是会报错的,因为实际执行的sql语句是:
select * from t_user order by loginName “asc” //那这俩单引号是什么鬼嘛,执行肯定报错啊,所以这时只能选择 Statement

String sql = "select * from t_user order by loginName ?";
ps = connection.prepareStatement(sql);
ps.setString(1,"asc");
resultSet = ps.executeQuery();

2)假设使用 Statement:

statement = connection.createStatement();
String sql = "select * from t_user order by loginName asc";
resultSet = statement.executeQuery(sql);
    while (resultSet.next()) {
    System.out.println(resultSet.getString("loginName"));
}

这样就可以根据 loginName 首字母大小升序的方式来输出 loginName:

abc
wwe

Process finished with exit code 0

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/5581.html

(0)
上一篇 2023-05-03
下一篇 2023-05-03

相关推荐

  • 数据安全 企业_物联网安全攻击

    数据安全 企业_物联网安全攻击2020年1月,时间跨度长达14年的,微软2.5亿条客户服务和支持记录在网上泄露; 同年4月,微盟发生史上最贵“删库跑路”事件,造成微盟市值一夜之间缩水约24亿港币; 今年7月,网信办依据《数据安全法

    2023-06-19
    89
  • (LNMP) Nginx_PHP_MariaDB「建议收藏」

    (LNMP) Nginx_PHP_MariaDB「建议收藏」L用的是Centos7.5以上,主要是NMP三组件的安装记录。 通常会先安装一下依赖: yum install -y pcre-devel zlib-devel openssl-devel 使用yum

    2022-12-29
    103
  • Mysql 多表连接查询 inner join 和 outer join 的使用「建议收藏」

    Mysql 多表连接查询 inner join 和 outer join 的使用「建议收藏」JOIN的含义就如英文单词“join”一样,连接两张表,大致分为内连接,外连接,右连接,左连接,自然连接。这里描述先甩出一张用烂了的图,然后插入测试数据。 首先先列举本篇用到的分类(内连接,外连接,…

    2023-01-31
    98
  • Postgresql 数据命令行导入导出操作「建议收藏」

    Postgresql 数据命令行导入导出操作「建议收藏」导入 COPY cnt_topholder_balance(datetime,chain,crypto,address,balance) FROM '/tmp/cnt_topholder_…

    2022-12-15
    100
  • Python Debug Assertion Failure及如何解决

    Python Debug Assertion Failure及如何解决Python Debug Assertion Failure是指Python程序在运行过程中出现了某些问题,导致Python进程被迫退出,并在控制台输出了一些错误信息。这种错误一般都会带有一个Debug Assertion Failure的标志,提示开发者在代码中出现了一些断言错误。断言是一种常用的编程技巧,用来在代码运行过程中判断某些条件是否满足,从而确保代码的正确性。由于断言通常只在开发阶段用于调试,所以在生产环境中被禁用,也就不会出现Debug Assertion Failure错误。

    2024-02-29
    56
  • PostgreSQL源码学习–插入数据#6[亲测有效]

    PostgreSQL源码学习–插入数据#6[亲测有效]本节介绍ExecModifyTable函数。 相关数据结构 typedef struct ModifyTableState { PlanState ps; /* its first field is…

    2023-03-09
    97
  • oracle数据库迁移相关SQL语句「终于解决」

    oracle数据库迁移相关SQL语句「终于解决」本人是使用PLSQL工具来做数据库迁移,示例是将同一个数据库的apps用户的数据迁移至sccsrm用户,它们都是在同一个数据库里。 数据库迁移常见的一种方式是使用命令将某个用户的所有数据导出,再将其…

    2023-02-23
    106
  • Kingbase 全局临时表[通俗易懂]

    Kingbase 全局临时表[通俗易懂]Postgresql 支持会话级别的临时表,表的存续期只在创建临时表的会话存活期间,会话退出后,临时表自动删除,表结构及数据也无法跨会话共享。KINGBASE除了支持PG原生的临时表机制外,还支持类似

    2023-04-17
    106

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注