美文网首页Java
6.JDBC学习笔记

6.JDBC学习笔记

作者: Vincilovfang | 来源:发表于2018-02-21 12:12 被阅读135次

    本文内容

    1.什么是JDBC以及为什么要使用JDBC

    2.JDBC核心API的讲解

    3.使用JDBC核心API进行CRUD操作

    4.JDBC的工具类的抽取与改进

    5.JDBC的SQL注入漏洞分析与解决方案

    6.使用JDBC的PreparedStatement预编译对象进行CRUD操作(重点)

    7.JDBC的批处理操作

    使用JDBC的预编译对象进行CRUD操作(重点)

    [if !supportLists]1.1 [endif]1.JDBC的概述

    JDBC:(Java DataBase Connectivity Java数据库连接).

    *是一种用于执行SQL语句的Java 的API.可以为多种关系型数据库提供统一的访问.它是由一组使用Java语言编写的类或接口组成.

    简说:用java语言编写的一组用于访问关系型数据库的接口和类.

    作用:使用Java语言连接到数据库

    驱动:两个设备之间的通信桥梁.

    Java语言要连接数据库必须使用数据库的驱动

    本质:

    SUN公司提供了一组接口,各个数据库生产商提供了这套接口的实现.(这组规范就是JDBC规范.)

    [if !supportLists]1.2 [endif]02_JDBC的入门(写)

    先解释下,再写

    设置工作空间的编码为utf-8

    SQL脚本:

    create database web_test3;

    use web_test3;

    create table user(

    id int primary key auto_increment,

    username varchar(20),

    password varchar(20),

    nickname varchar(20),

    age int

    );

    insert into user values (null,'aaa','123','小丽',34);

    insert into user values (null,'bbb','123','大王',32);

    insert into user values (null,'ccc','123','小明',28);

    insert into user values (null,'ddd','123','大黄',21);

    引入数据库的驱动.

    注意:复制驱动包过来后,一定要选中, add to Build Path

    1.加载驱动.

    2.获得连接.

    获得语句(Statement )对象

    3.执行SQL

    4.释放资源.

    public class JDBCDemo1 {

    @Test

    /**

    * JDBC的入门

     */

    public void demo1() throws Exception{

    // 1.加载驱动

    Class.forName("com.mysql.jdbc.Driver");

    // 2.获得连接

    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/web_test3", "root", "abc"); //注意:密码改成你的密码

    // 3.基本操作:执行SQL

    // 3.1获得执行SQL语句的对象

    Statement statement = conn.createStatement();

    // 3.2编写SQL语句:

    String sql = "select * from user";

    // 3.3执行SQL:

    ResultSet rs = statement.executeQuery(sql);

    // 3.4遍历结果集:

    while(rs.next()){

    System.out.print(rs.getInt("id")+" ");

    System.out.print(rs.getString("username")+" ");

    System.out.print(rs.getString("password")+" ");

    System.out.print(rs.getString("nickname")+" ");

    System.out.print(rs.getInt("age"));

    System.out.println();

    }

    // 4.释放资源

    rs.close();

    statement.close();

    conn.close();

    }

    }

    [if !supportLists]1.3 [endif]03_DriverManager的介绍

    问题:

    DriverManager对象有什么作用?

    Ø为什么没有使用registerDriver()注册驱动?

    Ø获取连接的url路径的含义?

    1.DriverManager对象两个作用:①、注册驱动和②、获取连接;

    2.为什么使用没有使用registerDriver注册驱动?

    DriverManager类:

    原来这样写:

    DriverManager.registerDriver(new com.mysql.jdbc.Driver());

    com.mysql.jdbc.Driver源码:

    现在这样写:

    Class.forName(“com.mysql.jdbc.Driver”);//强制加载class到内存

    结论:直接调用registerDriver方法会导致驱动加载2次.

    [if !supportLists]3.[endif]获取连接的url路径的含义?

    [if !supportLists]1.4 [endif]04_Connection的介绍

    [if !supportLists]Ø [endif]Connection对象有哪些作用?

    有两个作用:①、创建执行SQL的Statement(语句)对象;②、管理事务

    作用一、创建执行sql语句的对象:

    作用二:管理事务

    总结:

    [if !supportLists]1.[endif]Connection对象的作用?

    获取语句对象

    Statement

     CallableStatement(后面Oracle说)

     PreparedStatement

    管理事务

    setAutoCommit(false);//手动开启事务

    ...

    ...

    commit()

    rollback();

    [if !supportLists]1.5 [endif]05_Statement的介绍

    [if !supportLists]Ø [endif]Statement对象有哪些作用?

    有两个作用:①、执行sql语句;②、进行批处理

    作用一:执行sql语句

    作用二:进行批处理:就是把几条sql语句添加到Statement对象命令列表中,一次性执行多条sql语句。

    [if !supportLists]1.6 [endif]06_ResultSet的介绍

    ResultSet代表select查询后的结果集

    方法:

    *向下移动光标.

    *获得结果集中整形数据.

    *获得结果集中字符串类型的数据:

    ...

    遍历结果集:

    * while(rs.next()){

    int id = rs.getInt("id");

    String username = rs.getString("username");

    String password = rs.getString("password");

    System.out.println(id+"    "+username+"    "+password);

    }

    获得结果集中的数据:

    * int id = rs.getInt("id");

    String username = rs.getString("username");

    String password = rs.getString("password");

    如果结果集中只有一条记录:

    * if(rs.next()){

    ...

    }

    原理:

    总结:

       1. Result rs = statement.executeQuery(“select * from user”);

       2.while(rs.next()) {

           rs.getInt(“id”);

    rs.getString(“username”);

    rs.getObject(“password”);

    rs.getInt(4);

    }

    [if !supportLists]1.7 [endif]07_JDBC的资源的释放

    Connection的使用原则:尽量要晚创建,尽量早释放!!!

    try{

    ..

    ...

    }catch(){...}

    finally {....}

    要掌握,看看代码,晚上写

    [if !supportLists]Ø [endif]掌握释放资源标准代码:一般释放资源的代码放到finally里面去执行

    finally {

    //5、方法资源

    if (resultSet!=null) {

    try {

    resultSet.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    resultSet=null;

    }

    if (statement!=null) {

    try {

    statement.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    statement=null;

    }

    if (conn!=null) {

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn=null;

    }

    }

    1、为什么对象调用了close()方法以后还要把对象手动赋值为null?

    资源释放的一段标准代码:

    // 4.释放资源.

    if (rs != null) {

    try {

    rs.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    rs = null; // 为了让JVM垃圾回收更早回收该对象.

    }

    if (stmt != null) {

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if (conn != null) {

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    总结:

    try {

    //加载驱动

    //获取连接

    //创建statement

    //执行SQL

    //遍历结果集

    }catch(Exception ex) {

    }finally {

    //释放资源

    rs,stat,conn

    if (rs!=null) {

    try {

    rs.close();

    }catch() {}

    rs = null;

    }

    }

    [if !supportLists]1.8 [endif]08_JDBC的CRUD操作之保存(写)

    思路:

    加载驱动

    获得连接

    获得Statement对象,执行SQL

    释放资源

    @Test

    /**

    *保存操作的代码实现

     */

    public void demo1(){

    Connection conn = null;

    Statement stmt = null;

    try{

    //注册驱动:

    Class.forName("com.mysql.jdbc.Driver");

    //获得连接:

    conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

    //执行操作:

    //创建执行SQL语句对象:

    stmt = conn.createStatement();

    //编写SQL语句:

    String sql = "insert into user values (null,'eee','123','阿黄',21)";

    //执行SQL语句:

    int num = stmt.executeUpdate(sql);

    if(num > 0){

    System.out.println("保存用户成功!!!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    //资源释放:

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    }

    [if !supportLists]1.9 [endif]09_JDBC的CRUD操作之修改操作(写)

        @Test

    /**

    *修改操作的代码实现

     */

    public void demo2(){

    Connection conn = null;

    Statement stmt  = null;

    try{

    //注册驱动:

    Class.forName("com.mysql.jdbc.Driver");

    //获得连接

    conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

    //执行操作:

    //创建执行SQL语句的对象:

    stmt = conn.createStatement();

    //编写SQL语句:

    String sql = "update user set password='abc',nickname='旺财' where id = 5";

    //执行SQL语句:

    int num = stmt.executeUpdate(sql);

    if(num > 0){

    System.out.println("修改用户成功!!!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    //资源释放:

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    }

    [if !supportLists]1.10 [endif]10_JDBC的CRUD操作之删除操作

    @Test

    /**

    *删除操作的代码实现

     */

    public void demo3(){

    Connection conn = null;

    Statement stmt = null;

    try{

    //注册驱动:

    Class.forName("com.mysql.jdbc.Driver");

    //获得连接:

    conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

    //创建执行SQL语句对象:

    stmt = conn.createStatement();

    //编写SQL:

    String sql = "delete from user where id = 5";

    //执行SQL:

    int num = stmt.executeUpdate(sql);

    if(num > 0){

    System.out.println("删除用户成功!!!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    //资源释放:

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    }

    [if !supportLists]1.11 [endif]11_JDBC的CRUD操作之查询操作

    @Test

    /**

    *查询多条记录

     */

    public void demo4(){

    Connection conn = null;

    Statement stmt = null;

    ResultSet rs = null;

    try{

    //注册驱动

    Class.forName("com.mysql.jdbc.Driver");

    //获得连接

    conn = DriverManager.getConnection("jdbc:mysql:///web_test3", "root", "abc");

    //执行操作

    //创建执行SQL语句的对象:

    stmt = conn.createStatement();

    //编写SQL:

    String sql = "select * from user";

    //执行SQL:

    rs = stmt.executeQuery(sql);

    //遍历结果集:

    while(rs.next()){

    System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    //资源释放:

    if(rs != null){

    try {

    rs.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    rs = null;

    }

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    }

    [if !supportLists]1.12 [endif]12_JDBC的工具类的抽取(写)

    [if !supportLists]Ø [endif]总结一下抽取的原则:把相同的操作抽到一个方法里,可以重复利用。

    关于JDBC我们可以抽取:加载驱动、获取连接、释放资源这三部分的代码。

    /**

    * JDBC的工具类

     * @author  itheima

     */

    public class JDBCUtils {

    private static final String driverClassName;

    private static final String url;

    private static final String username;

    private static final String password;

    static{

    driverClassName="com.mysql.jdbc.Driver";

    url="jdbc:mysql:///web_test3";

    username="root";

    password="abc";

    }

    /**

    *注册驱动的方法

     */

    public static void loadDriver(){

    try {

    Class.forName(driverClassName);

    } catch (ClassNotFoundException e) {

    e.printStackTrace();

    }

    }

    /**

    *获得连接的方法

     */

    public static Connection getConnection(){

    Connection conn = null;

    try{

    //将驱动一并注册:

    loadDriver();

    //获得连接

    conn = DriverManager.getConnection(url,username, password);

    }catch(Exception e){

    e.printStackTrace();

    }

    return conn;

    }

    /**

    *释放资源的方法

     */

    public static void release(Statement stmt,Connection conn){

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    public static void release(ResultSet rs,Statement stmt,Connection conn){

    //资源释放:

    if(rs != null){

    try {

    rs.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    rs = null;

    }

    if(stmt != null){

    try {

    stmt.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    stmt = null;

    }

    if(conn != null){

    try {

    conn.close();

    } catch (SQLException e) {

    e.printStackTrace();

    }

    conn = null;

    }

    }

    }

    测试工具类

    @Test

    /**

    *查询操作:使用工具类

     */

    public void demo1(){

    Connection conn = null;

    Statement stmt = null;

    ResultSet rs = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    // 创建执行SQL语句的对象:

    stmt = conn.createStatement();

    //编写SQL:

    String sql = "select * from user";

    //执行查询:

    rs = stmt.executeQuery(sql);

    //遍历结果集:

    while(rs.next()){

    System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password"));

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    //释放资源:

    JDBCUtils.release(rs, stmt, conn);

    }

    }

    [if !supportLists]1.13 [endif]13_JDBC的配置信息提取到配置文件

    [if !supportLists]Ø [endif]如何定义配置文件以及加载配置文件中的信息?

    定义配置文件:

    获取配置文件中的信息:

    [if !supportLists]1.14 [endif]14_JDBC的SQL注入漏洞(SQL演示)

    [if !supportLists]Ø [endif]什么是sql注入漏洞?

    在我们的网站中肯定会有登录的操作,用户之所以能登录成功,肯定是通过用户名和对应的密码去数据库中能找到对应的一条数据,假设某个人不清楚密码,只通过输入用户名就能从数据库中找到一条对应的数据,那么这就称为sql注入漏洞。

    简单说:

    通过表单或界面输入一些SQL字符串,能到达服务器执行,达到非法操作的目的.

    正常的基本登录流程代码: 

    sql注入代码演示:

    输入用户名

    [if !supportLists]n [endif]aaa’ or ‘1=1密码随意

    [if !supportLists]n [endif]aaa’ -- 密码随意  注意:--后面有空格

    SQL环境演示:

    SELECT * FROM USER WHERE username='aaa' AND PASSWORD='123'

    SELECT * FROM USER WHERE username='aaa' OR '1=1' AND PASSWORD='wrwrw'

    SELECT * FROM USER WHERE username='aaa'-- ' AND PASSWORD='wrwrw'

    代码参见:/jdbc/src/com/itheima/jdbc/demo4/UserDao.java

    [if !supportLists]1.15 [endif]15_JDBC的SQL注入漏洞分析及解决

    [if !supportLists]Ø [endif]sql注入漏洞的原因是什么?

    [if !supportLists]Ø [endif]如何解决sql注入的漏洞?

    [if !supportLists]1、 [endif]原因:主要是用户输入了sql中规定的关键字,导致我们的sql语句的判断条件发生了变化。

    使用Statement对象来执行一个sql语句是这样的:

    resultSet=statement.executeQuery("select * from user where username='"+username+"' and password='"+password+"';");

       我们把用户输入的内容放到上面的sql语句对应的变量处:

    or前面的一部分判断成立就能查到结果。

    [if !supportLists]2、 [endif]解决sql注入的漏洞:使用PreparedStatement对象而不是Statement对象。

    PreparedStatement有一个预编译的过程,这个过程会固定sql语句的格式,对于变量要求是用?来占位,那么传递过来的数据即使包含了sql关键字也不会当做关键字来识别。

    public class UserDao {

    public boolean login(String username,String password){

    Connection conn = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

    //定义一个变量:

    boolean flag = false;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL语句:

    String sql = "select * from user where username = ? and password = ?";

    //预编译SQL

    pstmt = conn.prepareStatement(sql);

    //设置参数:

    pstmt.setString(1, username);

    pstmt.setString(2, password);

    //执行SQL语句:

    rs = pstmt.executeQuery();//无需传入SQL

    if(rs.next()){

    //说明根据用户名和密码可以查询到这条记录

    flag = true;

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(rs, pstmt, conn);

    }

    return flag;

    }

    代码参见:/jdbc/src/com/itheima/jdbc/demo4/UserDao.java

    [if !supportLists]1.16 [endif]16_JDBC的CRUD操作之PreparedStatement保存操作(写)

    @Test

    /**

    *保存操作

     */

    public void demo1(){

    Connection conn = null;

    PreparedStatement pstmt = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL语句:

    String sql = "insert into user values (null,?,?,?,?)";

    //预编译SQL:

    pstmt = conn.prepareStatement(sql);

    //设置参数:

    pstmt.setString(1, "eee");

    pstmt.setString(2, "abc");

    pstmt.setString(3, "旺财");

    pstmt.setInt(4, 32);

    //执行SQL

    int num = pstmt.executeUpdate();//不传SQL

    if(num > 0){

    System.out.println("保存成功!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(pstmt, conn);

    }

    }

    [if !supportLists]1.17 [endif]17_JDBC的CRUD操作之PreparedStatement修改操作

    @Test

    /**

    *修改操作

     */

    public void demo2(){

    Connection conn = null;

    PreparedStatement pstmt = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL语句:

    String sql = "update user set username = ?,password =?,nickname=?,age = ? where id = ?";

    //预编译SQL:

    pstmt = conn.prepareStatement(sql);

    //设置参数:

    pstmt.setString(1, "abc");//设置第一个?的值

    pstmt.setString(2, "1234");

    pstmt.setString(3, "旺旺");

    pstmt.setInt(4, 23);

    pstmt.setInt(5, 4);

    //执行SQL:

    int num = pstmt.executeUpdate();

    if(num > 0){

    System.out.println("修改成功!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(pstmt, conn);

    }

    }

    [if !supportLists]1.18 [endif]18_JDBC的CRUD操作之PreparedStatement删除操作

    @Test

    /**

    *删除操作

     */

    public void demo3(){

    Connection conn = null;

    PreparedStatement pstmt  = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL语句:

    String sql = "delete from user where id = ?";

    //预编译SQL

    pstmt = conn.prepareStatement(sql);

    //设置参数:

    pstmt.setInt(1, 4);

    //执行SQL:

    int num = pstmt.executeUpdate();

    if(num > 0){

    System.out.println("删除成功!");

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(pstmt, conn);

    }

    }

    [if !supportLists]1.19 [endif]19_JDBC的CRUD操作之PreparedStatement查询操作

    @Test

    /**

    *查询操作

     */

    public void demo4(){

    Connection conn = null;

    PreparedStatement pstmt = null;

    ResultSet rs = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL:

    String sql = "select * from user";

    //预编译SQL:

    pstmt = conn.prepareStatement(sql);

    //设置参数:

    //执行SQL:

    rs = pstmt.executeQuery();

    //遍历结果集:

    while(rs.next()){

    System.out.println(rs.getInt("id")+" "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname"));

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(rs, pstmt, conn);

    }

    }

    [if !supportLists]1.20 [endif]20_JDBC的批处理操作

    批处理:一批SQL一起执行

    @Test

    /**

    *批处理基本操作

     */

    public void demo1(){

    Connection conn = null;

    Statement stmt = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //创建执行批处理对象:

    stmt = conn.createStatement();

    //编写一批SQL语句:

    String sql1 = "create database test1";

    String sql2 = "use test1";

    String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";

    String sql4 = "insert into user values (null,'aaa')";

    String sql5 = "insert into user values (null,'bbb')";

    String sql6 = "insert into user values (null,'ccc')";

    String sql7 = "update user set name = 'mmm' where id = 2";

    String sql8 = "delete from user where id = 1";

    //添加到批处理

    stmt.addBatch(sql1);

    stmt.addBatch(sql2);

    stmt.addBatch(sql3);

    stmt.addBatch(sql4);

    stmt.addBatch(sql5);

    stmt.addBatch(sql6);

    stmt.addBatch(sql7);

    stmt.addBatch(sql8);

    //执行批处理:

    stmt.executeBatch();

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(stmt, conn);

    }

    }

    批量插入(使用PreparedStatement)

    @Test

    /**

    *批量插入记录:

    *需要在url后面拼接一个参数即可,效率高

             ?rewriteBatchedStatements=true

     */

    public void demo2(){

    //记录开始时间:

    long begin = System.currentTimeMillis();

    Connection conn = null;

    PreparedStatement pstmt = null;

    try{

    //获得连接:

    conn = JDBCUtils.getConnection();

    //编写SQL语句:

    String sql = "insert into user values (null,?)";

    //预编译SQL:

    pstmt = conn.prepareStatement(sql);

    for(int i=1;i<=10000;i++){

    pstmt.setString(1, "name"+i);

    //添加到批处理

    pstmt.addBatch();

    //注意问题:

    //执行批处理

    if(i % 1000 == 0){

    //执行批处理:

    pstmt.executeBatch();

    //清空批处理:

    pstmt.clearBatch();

    }

    }

    }catch(Exception e){

    e.printStackTrace();

    }finally{

    JDBCUtils.release(pstmt, conn);

    }

    long end = System.currentTimeMillis();

    System.out.println((end-begin));

    }

    1.21总结:

    阐述什么是JDBC以及为什么要使用JDBC

    独立完成使用JDBC核心API对数据库表记录的CRUD操作(重点)

    完成JDBC工具类的抽取与改进(重点)

    阐述什么是SQL注入漏洞并给出解决方法

    独立完成使用JDBC的预编译对象进行CRUD操作(重点)

    JDBC的批处理操作

    相关文章

      网友评论

        本文标题:6.JDBC学习笔记

        本文链接:https://www.haomeiwen.com/subject/zrontftx.html