JDBC 编程学习

前言

将最近学习的JDBC编程整理成笔记,做次记录。

mysql 安装

首先安装mysql 8.0.19 版本数据库。
下载地址 https://downloads.mysql.com/archives/community/
下载完成后点击默认安装即可。

image.png
image.png

默认安装到了C:\Program Files\MySQL\MySQL Server 8.0\bin目录下。
关于mysql的一些命令:

mysqld.exe --initialize-insecure 初始化数据库,执行后会生成data文件夹
mysqld.exe --install  安装mysql服务
net start mysql  启动mysql服务
set password for root@localhost = password('password');  修改密码
flush privileges 刷新权限

JDBC 简介

JDBC全称是Java DataBase Connectivity的缩写,是Java程序访问数据库的标准接口。
使用java里面提供的一些类和方法,利用程序链接数据库,进行增删改查,这个过程叫JDBC编程。
要实现JDBC编程,除了java.sql标准库,还需要找一个MySQL的JDBC驱动。其实就是一个第三方jar包。

这里下载mysql-connector-java-8.0.23 版本的jar包。 https://dev.mysql.com/downloads/connector/j/

下载后在eclipse 引入jar包。

image.png

并添加到项目库。

image.png

JDBC 编程

JDBC编程主要分为六步操作:

  1. 加载驱动程序
  2. 连接数据库
  3. 获取数据库操作对象
  4. 执行sql语句
  5. 处理查询结果集
  6. 释放连接

举个栗子:
实现最简单的查询语句

package jdbc_test;

import java.sql.*;

public class jdbcdemo01 {
    /**
     * 
     * @param username
     * @param password
     * @throws SQLException 
     */
    public static void main(String[] args) throws SQLException {
        Connection conn=null;
        Statement stmt=null;
        ResultSet rs=null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");//加载驱动
            
            String url = "jdbc:mysql://localhost:3306/web?useUnicode=true&characterEncoding=UTF8&userSSL=true";
            String user = "root";
            String pass = "";
            conn = DriverManager.getConnection(url,user,pass);//获取连接
            stmt = conn.createStatement();//获取数据库操作对象
            String sql = "select * from user";
            rs = stmt.executeQuery(sql);//执行sql语句
            
            while(rs.next()) {
                System.out.print(rs.getInt(1)+","+rs.getString("username")+","+rs.getString(3)+","+rs.getString(4));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
            rs.close();
            stmt.close();
            conn.close();
        }
    }
}

注意:url地址的完整度,执行查询语句用的是executeQuery方法,以及驱动连接用的是Class.forName()
还有一种方式也可以实现。

DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());// 第二种

new com.mysql.cj.jdbc.Driver()创建对象的时候本质上也执行了DriverManager.registerDriver(driver),这样一来就重复了,所以我们更习惯使用Class.forName()

第二个例子,更新语句

package jdbc_test;

import java.sql.*;

public class jdbcdemo01 {
    /**
     * 
     * @param username
     * @param password
     * @throws SQLException 
     */
    public static void main(String[] args) throws SQLException {
        Connection conn=null;
        Statement stmt=null;
        
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");//加载驱动
            String url = "jdbc:mysql://localhost:3306/web?useUnicode=true&characterEncoding=UTF8&userSSL=true";
            String user = "root";
            String pass = "";
            conn = DriverManager.getConnection(url,user,pass);//获取连接
            stmt = conn.createStatement();//获取数据库操作对象
            String sql = "update user set loginpwd=123456789 where id=1";
            int count = stmt.executeUpdate(sql);//执行sql语句
            System.out.println(count == 1 ? "更新成功" : "更新失败");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //释放资源
            stmt.close();
            conn.close();
        }
    }
}

注意:更新方法用的是executeUpdate,包括插入、删除、更新,并返回一个int值,所以自然也没有查询记过集
区分一下这两个方法。

int executeUpdate(insert/delete/update)
Resultset executeQuery(select)

PreparedStatement 对象

在了解PreparedStatement对象之前,先设计一个登录的demo,并尝试一种工具类提取的方式编写代码。
首先新建db.properties文件,提取出连接数据库的信息。

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/web?useUnicode=true&characterEncoding=UTF8&userSSL=true
username=root
password=

再提取出jdbc连接工具类JdbcUtils.java

package jdbc_test;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.*;

// 提取工具类
public class JdbcUtils {
    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;
    
    
    static {
        InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
        Properties properties = new Properties();
        try {
            properties.load(in);
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            
            // 加载驱动
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 获取连接
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url,username,password);
    }
    
    // 释放连接资源
    public static void release(Connection conn,Statement st,ResultSet rs) {
            if(rs!=null) {try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }}
            if(st!=null) {try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }}
            if(conn!=null) {try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }}
    }

}

最后再编写jdbcDemo3.java,来实现用户登录。
jdbcDemo3.java

package jdbc_test;

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


public class jdbcdemo3 {
    
    public static void main(String[] args) {
        Map userlogininfo = loginit();
        String loginName = (String) userlogininfo.get("username");
        String loginPwd = (String) userlogininfo.get("password");
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            stmt = conn.createStatement();
            String sql = "select * from user where loginName='"+loginName+"' and loginPwd='"+loginPwd+"' ";
            rs = stmt.executeQuery(sql);
            if(rs.next()) {
                System.out.print("login success");
            }else {
                System.out.print("login false");
            }
        }catch (Exception e) {
             e.printStackTrace();
        }finally {
            JdbcUtils.release(conn, stmt, rs);
        }
    }
     private static Map loginit() {
            Scanner s = new Scanner(System.in);
            System.out.print("username:");
            String username = s.nextLine();
            System.out.print("password:");
            String password = s.nextLine();
            Map userlogininfo = new HashMap();
            userlogininfo.put("username",username);
            userlogininfo.put("password",password);
            return userlogininfo;
            
        }
}

尝试登录。

image.png

但是该编写方式存在sql注入问题,当用户输入特殊的用户名、密码时,也可以登录成功。
a' or 1='1

image.png

这是因为真值 or 真值 and 假值 or 真值,结果即为真值。会查询出所有结果。

image.png

那么该如何解决sql注入的问题呢?这就有了PreparedStatement 对象。
该对象用来防止sql注入,是Statement的子类,可对sql进行预编译,从而提高数据库的执行效率。
修改jdbcDemo3.java

package jdbc_test;

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


public class jdbcdemo3 {
    
    public static void main(String[] args) {
        Map userlogininfo = loginit();
        String loginName = (String) userlogininfo.get("username");
        String loginPwd = (String) userlogininfo.get("password");
        Connection conn = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from user where loginName = ? and loginPwd= ? ";
            //?代表占位符,不能使用单引号括起来
            stmt = conn.prepareStatement(sql);//sql语句的预先编译
            //再给占位符传值,即使再注入,sql语句也没有编译
            stmt.setString(1, loginName);
            stmt.setString(2, loginPwd);
            rs = stmt.executeQuery();//执行sql语句
            if(rs.next()) {
                System.out.print("login success");
            }else {
                System.out.print("login false");
            }
        }catch (Exception e) {
             e.printStackTrace();
        }finally {
            JdbcUtils.release(conn, stmt, rs);
        }
    }
     private static Map loginit() {
            Scanner s = new Scanner(System.in);
            System.out.print("username:");
            String username = s.nextLine();
            System.out.print("password:");
            String password = s.nextLine();
            Map userlogininfo = new HashMap();
            userlogininfo.put("username",username);
            userlogininfo.put("password",password);
            return userlogininfo;
            
        }
}

注意:无法sql注入就是因为PreparedStatement 对象在执行sql语句时先进行了预编译

image.png

总结

学习了JDBC的基本过程,复习了db.properties文件、代码层的sql注入,蛮有收获,继续加油。

参考资料

https://www.bilibili.com/video/BV1NJ411J79W?p=36

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容