2.【JDBC相关对象功能详解】

  • DriverManager:驱动管理对象
  • Connection:数据库连接对象
  • Statement:执行sql的对象
  • ResultSet:结果集对象
  • PreparedStatement:执行sql的对象

DriverManager

驱动管理对象,主要功能如下:

  1. 注册驱动
  2. 获取数据库连接对象

1. 注册驱动

  • 告诉程序该使用哪一个数据库驱动(填写jar包中Driver类的路径)
// 注册与给定的驱动程序 DriverManager 
static void registerDriver(Driver driver) :

通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块

static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}

注意:mysql5之后的驱动jar包可以省略注册驱动的步骤(jar包中有文件java.sql.Driver)。

写代码时使用此方法

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

2. 获取数据库连接对象

方法:

static Connection getConnection(String url, String user, String password) 

参数:

  • user:用户名

  • password:密码

  • url:指定连接的路径

jdbc:mysql://ip地址(域名):端口号/数据库名称

例如:

jdbc:mysql://localhost:3306/db3

细节:

  • 如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:
jdbc:mysql:///数据库名称

Connection

数据库连接对象,主要功能如下:

  • 获取执行sql 的对象
  • 管理事务

1. 获取执行sql的对象

// 两种
Statement createStatement()  
PreparedStatement prepareStatement(String sql)  

2. 管理事务

  • 开启事务:

调用该方法设置参数为false,即开启事务

setAutoCommit(boolean autoCommit)
  • 提交事务:
commit() 
  • 回滚事务:
rollback() 

Statement

执行sql的对象,用于执行静态SQL语句并返回器生成的结果的对象。

  • 可以执行任意的sql
boolean execute(String sql) 
  • 执行DQL(select)语句
// 返回的是结果集对象
ResultSet executeQuery(String sql) 
  • 执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句
int executeUpdate(String sql)

返回的是影响的行数,判断DML语句是否执行成功:返回值大于零。DDL:只返回0。

功能演示

  • 对account表进行添加一条记录
package cn.luis.demo1.jdbc;

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

/**
 * @ClassName JDBCDemo2
 * @Description 对表添加一条记录
 * @Author L
 * @Date 2020.01.17 21:31
 * @Version 1.0
 * @Remark account表 添加一条记录 insert 语句
 **/
public class JDBCDemo2 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 1.注册驱动(填写jar包中Driver类的路径)
            Class.forName("com.mysql.jdbc.Driver");
            // 2.定义sql
            String sql = "insert into account values(null,'王五',3000)";
            // 3.获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
            // 4.获取执行sql的对象,Statement
             stmt = conn.createStatement();
            // 5.执行sql
            int count = stmt.executeUpdate(sql); // 影响的行数
            // 6.处理结果
            System.out.println("影响的行数:" + count);
            if(count > 0) {
                System.out.println("添加成功!");
            } else {
                System.out.println("添加失败!");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 7.释放资源
            // stmt.close();
            // 避免空指针异常(上面4.语句执行出错就会发生空指针异常)
            if (stmt != null) { // 若为空,代表并未申请资源,也就不用释放了
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
			// 避免空指针异常(上面2.语句执行出错就会发生空指针异常)
            if (conn != null) { // 若为空,代表并未申请资源,也就不用释放了
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果:

影响的行数:1
添加成功!
  • 创建一张Student表
package cn.luis.demo1.jdbc;

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

/**
 * @Description 执行DDL语句
 * @Author L
 * @Date 2020.01.17 22:11
 * @Version 1.0
 * @Remark 创建一张表
 **/
public class JDBCDemo5 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取数据库连接对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3","root","root");
            // 3.定义sql语句
            String sql = "create table student (id int,name varchar(20))";
            // 4.获取执行sql对象
            stmt = conn.createStatement();
            // 5.执行sql(影响的行数)
            int count = stmt.executeUpdate(sql);
            // 6.处理结果
            System.out.println(count); // 0 没有返回值
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            // 7.释放资源
            /*
                若程序还未执行到Stetement就抛出异常,此时stmt为null,
                尚未申请资源,也就不用释放了,调用close()方法就会报错!
            */
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

结果:

0

释放资源时需注意

若程序还未执行到Stetement就抛出异常,此时stmt为null,尚未申请资源,也就不用释放了,调用close()方法就会报错!【Connection类似】

 if (stmt != null) { 
     ...
 }

ResultSet

结果集对象,用于封装查询结果

获取封装数据的两个步骤

  • 游标向下移动一行

    返回值:布尔值,判断当前行是否是最后一行末尾(是否有数据)。

    ​ 如果是,则返回false,如果不是则返回true

boolean next():
  • 获取数据

    Xxx:代表数据类型 如: getInt() 、getString()

  • 参数

    • int:代表列的编号,从1开始 如: getString(1)
    • String:代表列名称。 如: getDouble(“表的列名”)
 getXxx(参数):
使用步骤
  1. 游标向下移动一行
  2. 判断该行是否有数据
  3. 获取数据
  • 代码演示:
/*
	6.处理结果,省略其他部分代码
*/
// 6.1让光标向下移动一行,循环判断游标是否到达最后一行末尾,并判断是否有数据
while(rs.next()) {  
    // 6.2获取数据
    int id = rs.getInt(1);
    String name = rs.getString("name");
    double balance = rs.getDouble("balance");
    System.out.println(id + "---" + name + "---" + balance);
}
// 释放rs资源
案例

定义一个方法,查询emp表的数据将其封装为对象,然后装载集合,打印。

  1. 定义Emp
  2. 定义JDBC类
    • 定义方法 public List<Emp> findAll(){}
    • 注册驱动
    • 获取连接
    • 定义SQL语句
    • 获取执行SQL对象
    • 遍历结果集,创建EMP对象,封装数据
    • 装载List集合

代码演示:

  • Emp实体类:略
  • JDBC类
package cn.luis.demo1.jdbc;

import cn.luis.demo2.domain.Emp;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName JDBCDemo9
 * @Description 定义一个方法
 * @Author L
 * @Date 2020.01.18 10:34
 * @Version 1.0
 * @Remark 查询emp表中数据将其封装为对象,然后装载集合,返回。
 **/
public class JDBCDemo9 {

    public static void main(String[] args) {
        List<Emp> list = new JDBCDemo9().findALL();
        System.out.println(list.size());
        for (Emp emp : list) {
            System.out.println(emp);
        }
    }
    /**
     * @Author Lius
     * @Description 查询所有emp对象
     * @Date 10:36 2020.01.18
     * @Param []
     * @Return java.util.List<cn.luis.demo2.domain.Emp>
     **/
    public List<Emp> findALL() {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        List<Emp> list = null;

        try {
            // 1.注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            // 2.获取连接
            conn = DriverManager.getConnection("jdbc:mysql:///db2", "root", "root");

            // 3.定义sql
            String sql = "select * from emp";
            // 4.获取执行sql对象
            stmt = conn.createStatement();
            // 5.执行sql语句
            rs = stmt.executeQuery(sql);
            // 6.遍历结果集,封装对象,装载集合
            // 创建emp对象
            Emp emp = null;
            list = new ArrayList<>();
            while (rs.next()) {
                // 6.处理结果("id"):要和数据库中的名称相同!!!
                int id = rs.getInt("id");
                String ename = rs.getString("ename");
                int job_id = rs.getInt("job_id");
                int mgr = rs.getInt("mgr");
                Date joindate = rs.getDate("joindate");
                double salary = rs.getDouble("salary");
                double bonus = rs.getDouble("bonus");
                int dept_id = rs.getInt("dept_id");
                // 创建emp对象
                emp= new Emp();
                emp.setId(id);
                emp.setEname(ename);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                // 装载集合
                list.add(emp);

            }
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        } finally {
            if(rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stmt != null) {
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }
}·

结果:

15
Emp{id=1001, ename='孙悟空', ... salary=10000.0, bonus=0.0, dept_id=20}
Emp{id=1002, ename='卢俊义', ... salary=16000.0, bonus=3000.0, dept_id=30}
...

PreparedStatement

执行sql的对象,解决sql注入问题

SQL注入问题

在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题 【静态sql易发生】

例如

  • 输入用户随便,输入密码:a’ or ‘a’ = 'a

    此时sql语句永远成立,会显示所有数据

select * from user where username = 'fhdsjkf' and password = 'a' or 'a' = 'a'

解决sql注入问题

使用PreparedStatement对象来解决

  • 预编译的SQL:参数使用 ? 作为占位符
select * from user where username = ? and password = ?;

步骤

  1. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
  2. 注册驱动
  3. 获取数据库连接对象 Connection
  4. 定义sql
select * from user where username = ? and password = ?;
  1. 获取执行sql语句的对象PreparedStatement
PreparedStatement pstmt = conn.prepareStatement(sql);
  1. ? 赋值:方法:setXxx(参数1,参数2)

    参数1:?的位置编号,从1 开始;

    参数2:?的值。

pstmt.setString(1,username);
pstmt.setString(2,password);
  1. 执行sql,接收返回结果

    不需要传递sql语句,在获取PreparedStatement已传入

pstmt.executeQuery();
  1. 处理结果

  2. 释放资源

注意

后期都会使用PreparedStatement来完成增删改查的所有操作

  • 可以防止SQL注入
  • 效率更高
代码实现
package cn.luis.demo1.jdbc;

import cn.luis.demo2.domain.Emp;
import cn.luis.demo3.util.JDBCUtils;

import java.sql.*;
import java.util.List;
import java.util.Scanner;

/**
 * @Description 定义一个方法
 * @Author L
 * @Date 2020.01.18 10:34
 * @Version 1.0
 * @Remark 
 **/
public class JDBCDemo12 {

    public static void main(String[] args) {
        // 1.键盘录入
        Scanner sc = new Scanner(System.in);
        System.out.print("输入用户名:");
        String username = sc.next();
        System.out.print("输入密码:");
        String password = sc.next();
        // 2.调用方法
        boolean flag = new JDBCDemo12().login(username, password);
        // 3.判断结果
        if(flag) {
            System.out.println("登陆成功!");
        } else {
            System.out.println("用户名或密码错误!");
        }

    }
    /**
     * @Author Lius
     * @Description 练习 登录方法,使用PreparedStatement实现
     * @Date 10:36 2020.01.18
     * @Param []
     * @Return java.util.List<cn.luis.demo2.domain.Emp>
     **/
    public boolean login(String username, String password) {
        if(username == null || password == null) {
            return false;
        }
        // 连接数据库

        // 1.获取连接
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {

            // 1.获取连接
            conn = JDBCUtils.getConnection();
            // 2.定义sql
            String sql = "select * from user where username = ? and password = ?";
            // 3.获取执行sql对象
            pstmt = conn.prepareStatement(sql);
            // 4.给 ? 赋值
            pstmt.setString(1,username);
            pstmt.setString(2,password);
            // 5.执行sql语句
            rs = pstmt.executeQuery();
            // 6.判断
            return rs.next(); // 如果有下一行,则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs,pstmt,conn);
        }
        return false;
    }
}

结果:

输入用户名:zhangsan
输入密码:123
登陆成功!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值