JDBC05-详解各个类2

1、DriverManager:驱动管理对象(类)

 功能:

  a. 注册驱动:告诉程序该使用哪一个数据库驱动jar包

    DriverManager下的方法 public static void registerDriver(java.sql.Driver driver):注册与给定的驱动程序DriverManager

    写代码使用:Class.forName("com.mysql.jdbc.Driver"); 把Driver类文件加载进内存,类里的代码会被自动执行。静态代码块的代码会被自动执行。

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

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

  注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。不过建议还是写上。

    即Class.forName("com.mysql.jdbc.Driver");可以省略。因为mysql5的jar包中META-INF->services->java.sql.Driver文件下存在“com.mysql.jdbc.Driver”,会自动地注册驱动。如果代码中没有注册会先读取java.sql.Driver文件去自动的注册驱动。

  b. 获取数据库连接

    • 方法:static Connection getConnection(String url, String user, String password) 尝试建立与给定数据库URL的连接。
    • 参数:
      • url:指定连接的路径

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

        例子:jdbc:mysql://localhost:3306/db3

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

      • user:用户名
      • password:密码

2、Connection:数据库连接对象(接口)

 java.sql.Connection功能:

  a. 获取执行sql的对象

    • java.sql.Statement createStatement():创建一个Statement对象,用于将SQL语句发送到数据库。
    • java.sql.PreparedStatement prepareStatement(String sql):创建一个PreparedStatement对象,用于将参数化的SQL语句发送到数据库。

  b. 管理事务

    • 开启事务:void setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务。将此连接的自动提交模式设置为给定状态。
    • 提交事务:void commit()。使自上次提交/回滚以来所做的所有更改都将永久性,并释放此Connection对象当前持有的任何数据库锁。
    • 回滚事务:void rollback()。撤销在当前事务中所做的所有更改,并释放此Connection对象当前持有的任何数据库锁。

3、Statement:执行sql的对象(接口)

 用于执行静态SQL(里面参数都是给定值)语句并返回其生成的结果的对象。

 a. 执行sql

    • boolean execute(String sql):执行给定的SQL语句,这可能会返回多个结果。可以执行任意的sql,了解即可。
    • int executeUpdate(String sql):执行给定的SQL语句,这可能是 INSERT , UPDATE ,或 DELETE语句,或者不返回任何内容,如SQL DDL语句的SQL语句。执行DML(insert、update、delete)语句、DDL(create、alter、drop)语句。
      • 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值>0的则执行成功,反之则失败。
    • ResultSet executeQuery(String sql):执行给定的SQL语句,该语句返回单个ResultSet对象。执行DQL(select)语句。

4、练习

 1. account表添加一条记录

package cn.itcast.jdbc;

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

/**
 * account表添加一条记录 insert语句
 */
public class JDBCDemo2 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;
        //1. 注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            String sql = "insert into account values (null,'wangwu',3000)";
            //3. 获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            int count = stat.executeUpdate(sql);//count为影响的行数
            //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. 释放资源
            //避免空指针异常
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

 输出结果:

 

 2. account表修改记录

package cn.itcast.jdbc;

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

/**
 * account表修改记录
 */
public class JDBCDemo3 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;
        //1. 注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            String sql = "update account set balance = 1500 where id = 3";
            //3. 获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            int count = stat.executeUpdate(sql);//count为影响的行数
            //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. 释放资源
            //避免空指针异常
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

 输出结果:

 

 3. account表删除一条记录

package cn.itcast.jdbc;

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

/**
 * account表删除一条记录
 */
public class JDBCDemo4 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;
        //1. 注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            String sql = "delete from account where id = 3";
            //3. 获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            int count = stat.executeUpdate(sql);//count为影响的行数
            //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. 释放资源
            //避免空指针异常
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 输出结果:

 

 4. 新增Student表

package cn.itcast.jdbc;

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

/**
 * 执行DDL语句
 */
public class JDBCDemo5 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;
        //1. 注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            String sql = "create table student (id int , name varchar(20))";
            //3. 获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            int count = stat.executeUpdate(sql);//count为影响的行数
            //6. 处理结果
            System.out.println(count);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //7. 释放资源
            //避免空指针异常
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 输出结果:

 

5、ResultSet:结果集对象,封装查询结果(接口)

  • boolean next():将光标从当前位置向下移动一行。ResultSet光标最初位于第一行之前; 第一次调用方法next使第一行成为当前行; 第二个调用使第二行成为当前行,依此类推。当调用next方法返回false时,光标位于最后一行之后。
  • getXXX(参数):获取数据
    • XXX:代表数据类型。如:int getInt(),String getString()
    • 参数:
      • int:代表列的编号,从1开始。如:getString(1)
      • String:代表带名称。如:getDouble("balance")

      int getInt(int coulumnIndex)、int getInt(String columnLabel)、String getString(int coulumnIndex)、String getString(String columnLabel)

  • 注意:
    • 使用步骤:

      1. 游标向下移动一行

      2. 判断是否有数据

      3. 获取数据

package cn.itcast.jdbc;

import java.sql.*;

public class JDBCDemo7 {
    public static void main(String[] args) {
        Statement stat = null;
        Connection conn = null;
        ResultSet rs = null;
        //1. 注册驱动
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //2. 定义sql
            String sql = "select * from account";
            //3. 获取Connection对象
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            rs = stat.executeQuery(sql);//count为影响的行数
            //6. 处理结果
            //6.1 让游标向下移动一行,循环判断游标是否是最后一行末尾
            while(rs.next()){
                //6.2 获取数据
                int id = rs.getInt(1);
                String name = rs.getString("name");
                double balance = rs.getDouble(3);

                System.out.println(id + "---" + name + "---" + balance);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //7. 释放资源
            //避免空指针异常
            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

 输出结果:

 

6、练习

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

  1. 定义emp类

  2. 定义方法 public List<Emp> findAll(){}

  3. 实现方法 select * from emp;

package cn.itcast.jdbc;

import java.util.Date;

/**
 * 封装Emp表数据的JavaBean
 */
public class Emp {
    private int id;
    private String ename;
    private int job_id;
    private int mgr;
    private Date joindate;
    private double salary;
    private double bonus;
    private int dept_id;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public int getJob_id() {
        return job_id;
    }

    public void setJob_id(int job_id) {
        this.job_id = job_id;
    }

    public int getMgr() {
        return mgr;
    }

    public void setMgr(int mgr) {
        this.mgr = mgr;
    }

    public Date getJoindate() {
        return joindate;
    }

    public void setJoindate(Date joindate) {
        this.joindate = joindate;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public double getBonus() {
        return bonus;
    }

    public void setBonus(double bonus) {
        this.bonus = bonus;
    }

    public int getDept_id() {
        return dept_id;
    }

    public void setDept_id(int dept_id) {
        this.dept_id = dept_id;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "id=" + id +
                ", ename='" + ename + '\'' +
                ", job_id=" + job_id +
                ", mgr=" + mgr +
                ", joindate=" + joindate +
                ", salary=" + salary +
                ", bonus=" + bonus +
                ", dept_id=" + dept_id +
                '}';
    }
}
package cn.itcast.jdbc;

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

public class JDBCDemo8 {

    public static void main(String[] args) {
        List<Emp> list = new JDBCDemo8().findAll();
        System.out.println(list);
        System.out.println(list.size());
    }

    /**
     * 查询所有emp对象
     * @return
     */
    public List<Emp> findAll(){
        Connection conn = null;
        Statement stat = null;
        ResultSet rs = null;
        List<Emp> list = null;

        try {
            //1. 注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //2. 获取连接
            conn = DriverManager.getConnection("jdbc:mysql:///db3", "root", "root");
            //3. 定义sql
            String sql = "select * from emp";
            //4. 获取执行sql的对象 Statement
            stat = conn.createStatement();
            //5. 执行sql
            rs = stat.executeQuery(sql);
            //6. 遍历结果集,封装对象,装载集合
            Emp emp = null;
            list = new ArrayList<Emp>();
            while(rs.next()){
                //获取数据
                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");//这是java.sql.Date,是java.util.Date的子类
                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 e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //7. 释放资源
            //避免空指针异常
            if(rs != null){
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(stat != null){
                try {
                    stat.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(conn != null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }
}

 输出结果:

 

6、PreparedStatement:执行sql的对象,比Statement更强大(接口)

 表示预编译(动态)SQL语句的对象。

 1. SQL注入问题:在拼接sql时,有一些sql的特殊关键字参与字符串的拼接。会造成安全性问题。

  a. 输入用户随便,输入密码:a' or 'a' = 'a

  b. sql:select * from user where username = 'sdfweeyr' and password = 'a' or 'a' = 'a',执行此sql会查出来表中所有的数据

 2. 解决sql注入问题:使用PreparedStatement对象来解决

 3. 预编译的SQL:参数使用?作为占位符,执行sql时给?赋值即可。

    4. 使用PreparedStatement步骤:

  a. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar

  b. 注册驱动
  c. 获取数据库连接对象 Connection
  d. 定义sql

    注意:sql的参数使用?作为占位符。select * from user where username = ? and password = ?;

  e. 获取执行sql语句的对象PreparedStatement Connection.prepareStatement(String sql);

  f. 给?赋值:

    PreparedStatement方法:void setXXX(参数1, 参数2)  将指定参数设置为给定的Java int/double/String/boolean等值。 

    参数1:?的位置编号从1开始。int parameterIndex

    参数2:?的值

  g. 执行sql,接受返回结果,不需要传递sql语句

  h. 处理结果

  i. 释放资源

package cn.itcast.jdbc;

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

/**
 * 需求:
 *             1. 通过键盘录入用户名和密码
 *             2. 判断用户是否登录成功
 */
public class JDBCDemo11 {

    public static void main(String[] args) {
        //1. 键盘录入,接收用户名和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();

        //2. 调用方法
        JDBCDemo11 jdbcDemo11 = new JDBCDemo11();
        boolean flag = jdbcDemo11.login(username,password);

        //3. 判断结果,输出不同语句
        if(flag){
            System.out.println("登录成功!");
        }else{
            System.out.println("用户名或密码错误!");
        }
    }

    /**
     * 登录方法,使用Prepared Statement实现
     */
    public boolean login(String username,String password){

        if(username == null && password == null){
            return false;
        }
        Connection conn = null;
        PreparedStatement pstat = null;
        ResultSet rs = null;
        //连接数据库判断是否登录成功
        //1. 获取连接
        try {
            conn = JDBCUtils.getConnection();
            //2. 定义sql
            String sql = "select * from user where username= ? and password = ?";
            System.out.println(sql);
            //3. 获取执行sql的对象
            pstat = conn.prepareStatement(sql);
            //给?赋值
            pstat.setString(1,username);
            pstat.setString(2,password);
            //4. 执行查询,不需要传递sql
            rs = pstat.executeQuery();
            //5. 判断
            return rs.next();//如果有下一行则返回true
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, pstat, conn);
        }
        return false;
    }
}

 执行结果:

    

 5. 注意:后期都会使用PreparedStatement来完成增删改查的所有操作。

  a. 可以防止SQL注入

  b. 效率更高

 

posted on 2022-01-05 00:04  花溪月影  阅读(45)  评论(0编辑  收藏  举报