JavaWeb基础学习——JDBC

1. JDBC快速入门

/**
    JDBC快速入门
 */
public class JDBCDemo {
    public static void main(String[] args) throws Exception {
        // 1、注册驱动
        Class.forName("com.mysql.jdbc.Driver"); 

        // 2、获取连接
        String url = "jdbc:mysql://127.0.0.1:3306/db1";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3、定义sql
        String sql = "update account set money = 2000 where id = 1";

        // 4、获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();

        // 5、执行sql
        int count = stmt.executeUpdate(sql); //受影响的行数

        // 6、处理结果
        System.out.println(count);

        // 7、释放资源
        stmt.close();
        conn.close();
    }
}

2. JDBC API

2.1 DriverManager

  • 注册驱动
  • 获取数据库连接

在这里插入图片描述

		// 1、注册驱动
        // Class.forName("com.mysql.jdbc.Driver");//MySQL 5之后的驱动包,可以省略注册驱动的步骤

        // 2、获取连接:如果连接的是本机mysql,并且端口是默认的3306可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);

2.2 Connection

2.2.1 获取执行SQL的对象

  • 普通执行SQL对象
Statement createStatement()
  • 预编译SQL的执行SQL对象:防止SQL注入
PreparedStatement  prepareStatement(sql)
  • 执行存储过程的对象
CallableStatement prepareCall(sql)

2.2.2 管理事务

  • 开启事务
    在这里插入图片描述
  • 提交事务
    在这里插入图片描述
  • 回滚事务
    在这里插入图片描述
try {
            // 开启事务
            conn.setAutoCommit(false);
            // 5、执行sql
            int count1 = stmt.executeUpdate(sql1); //受影响的行数
            // 6、处理结果
            System.out.println(count1);
            int i = 3 / 0;
            // 5、执行sql
            int count2 = stmt.executeUpdate(sql2); //受影响的行数
            // 6、处理结果
            System.out.println(count2);

            // 提交事务
            conn.commit();
        } catch (Exception e) {
            // 回滚事务
            conn.rollback();
            e.printStackTrace();
        }

2.3 Statement

  • 执行DDL、DML语句
    在这里插入图片描述
  • 执行DQL语句
    在这里插入图片描述
 /**
     * 执行DML语句
     * @throws Exception
     */
    @Test
    public void testDML() throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "update account set money = 3000 where id = 1";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        int count = stmt.executeUpdate(sql);//执行完DML语句,受影响的行数
        //6. 处理结果
        //System.out.println(count);
        if (count > 0) {
            System.out.println("修改成功~");
        } else {
            System.out.println("修改失败~");
        }
        //7. 释放资源
        stmt.close();
        conn.close();
    }
/**
     * 执行DDL语句
     * @throws Exception
     */
    @Test
    public void testDDL() throws Exception {
        //1. 注册驱动
        //Class.forName("com.mysql.jdbc.Driver");
        //2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);
        //3. 定义sql
        String sql = "drop database db2";
        //4. 获取执行sql的对象 Statement
        Statement stmt = conn.createStatement();
        //5. 执行sql
        int count = stmt.executeUpdate(sql);//执行完DDL语句,可能是0
        //6. 处理结果
        System.out.println(count);
        
        //7. 释放资源
        stmt.close();
        conn.close();
    }

2.4 ResultSet

  • 封装DQL查询语句的结果
ResultSet  executeQuery(sql):执行DQL 语句,返回 ResultSet 对象
 /**
     * 执行DQL语句
     * @throws Exception
     */
    @Test
    public void testResultSet() throws Exception {
        // 1. 注册驱动
        // Class.forName("com.mysql.jdbc.Driver");
        // 2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "select * from account";

        // 4.获取Statement对象
        Statement stmt = conn.createStatement();

        // 5.执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 6.处理结果:遍历rs中的所有数据
        // 6.1 光标向下移动一行,并且判断当前行是否有数据
        /*while(rs.next()){
            // 6.2获取数据 getXxx()
            int id = rs.getInt("1");
            String name = rs.getString("2");
            double money = rs.getDouble("3");

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("-------------------");
        }*/
        while(rs.next()) {
            // 6.2获取数据 getXxx()
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            System.out.println(id);
            System.out.println(name);
            System.out.println(money);

            System.out.println("-------------------");
        }

        // 7.释放资源
        rs.close();
        stmt.close();
        conn.close();
    }
  • 案例
    需求:查询account账户表数据,封装为Account对象中,并且存储到ArrayList集合中。
/**
     * 查询ccount账户表数据,封装为Account对象中,并且存储到ArrayList集合中
     * 1. 定义实体类Account
     * 2. 查询数据,封装到Account对象中
     * 3. 将Account对象存入ArrayList集合中
     *
     * @throws Exception
     */
    @Test
    public void testResultSet2() throws Exception {
        // 1. 注册驱动
        // Class.forName("com.mysql.jdbc.Driver");
        // 2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        String url = "jdbc:mysql:///db1?useSSL=false";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 3.定义sql
        String sql = "select * from account";

        // 4.获取Statement对象
        Statement stmt = conn.createStatement();

        // 5.执行sql
        ResultSet rs = stmt.executeQuery(sql);

        // 创建集合
        List<Account> list = new ArrayList<>();

        // 6.处理结果:遍历rs中的所有数据
        // 6.1 光标向下移动一行,并且判断当前行是否有数据
        while(rs.next()) {
            Account account = new Account();

            // 6.2获取数据 getXxx()
            int id = rs.getInt("id");
            String name = rs.getString("name");
            double money = rs.getDouble("money");

            // 赋值
            account.setId(id);
            account.setName(name);
            account.setMoney(money);

            // 存入集合
            list.add(account);
        }

        System.out.println(list);


        // 7.释放资源
        rs.close();
        stmt.close();
        conn.close();
    }

2.5 PreparedStatement

  • 作用:预编译SQL语句并执行:预防SQL注入问题

2.5.1 SQL注入

  • SQL注入是通过操作输入来修改事先定义好的SQL语句,用以达到执行代码对服务器进行攻击的方法。

2.5.2 PreparedStatement

  1. 获取 PreparedStatement 对象
// SQL语句中的参数值,使用?占位符替代
String sql = "select * from user where username = ? and password = ?";
// 通过Connection对象获取,并传入对应的sql语句
PreparedStatement pstmt = conn.prepareStatement(sql);
  1. 设置参数值
PreparedStatement对象:setXxx(参数1,参数2):给 ? 赋值
  1. 执行SQL语句
executeUpdate();  执行DDL语句和DML语句
executeQuery();  执行DQL语句

2.5.3 PreparedStatement原理

PreparedStatement 好处:

  • 预编译SQL,性能更高
  • 防止SQL注入:将敏感字符进行转义
@Test
    public void preparedStatement2() throws Exception {
        // 1. 注册驱动
        // Class.forName("com.mysql.jdbc.Driver");
        // 2. 获取连接:如果连接的是本机mysql并且端口是默认的 3306 可以简化书写
        // useServerPrepStmts=true开启预编译功能
        String url = "jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true开启预编译功能";
        String username = "root";
        String password = "WLY755414220";
        Connection conn = DriverManager.getConnection(url, username, password);

        // 接收用户输入 用户名和密码
        String name = "zhangsan";
        String pwd = "' or '1' = '1";

        // 定义sql
        String sql = "select * from tb_user where username = ? and password = ?";

        // 获取pstmt
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 设置?的值
        pstmt.setString(1,name);
        pstmt.setString(2,pwd);

        // 执行sql
        ResultSet rs = pstmt.executeQuery();

        // 判断登录是否成功
        if (rs.next()){
            System.out.println("登陆成功~");
        }else{
            System.out.println("登录失败~");
        }

        // 7.释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }
  • 在获取PreparedStatement对象时,将sql语句发送给mysql服务器进行检查,编译(这些步骤很耗时)
  • 执行时就不用再进行这些步骤了,速度更快
  • 如果sql模板一样,则只需要进行一次检查、编译

3. 数据库连接池

3.1 简介

  • 数据库连接池是个容器,负责分配、管理数据库连接(Connection)
  • 它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个;
  • 释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏
  • 好处:
    资源重用
    提升系统响应速度
    避免数据库连接遗漏

3.2 实现

  • 标准接口:DataSource
Connection getConnection()

那么以后就不需要通过 DriverManager 对象获取 Connection 对象,而是通过连接池(DataSource)获取 Connection 对象。

/**
 * 配置文件
 */
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql:///db1?useSSL=false&useServerPrepStmts=true
username=root
password=1234
# 初始化连接数量
initialSize=5
# 最大连接数
maxActive=10
# 最大等待时间
maxWait=3000
/**
 * Druid 数据库连接池演示
 */
public class DruidDemo {
    public static void main(String[] args) throws Exception {
        // 1.导入jar包

        // 2.定义配置文件

        // 3.加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("jdbc-demo/src/druid.properties"));

        // 4.获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);

        // 5.获取数据库连接 Connection
        Connection connection = dataSource.getConnection();

        System.out.println(connection);
    }
}

4. 案例

完成商品品牌数据的增删改查操作

  • 查询:查询所有数据
  • 添加:添加品牌
  • 修改:根据id修改
  • 删除:根据id删除
    JavaWeb基础学习——JDBC_第1张图片

4.1 查询所有

    /**
     * 查询所有
     * 1. SQL:select * from tb_brand;
     * 2. 参数:不需要
     * 3. 结果:List
     */
    @Test
    public void testSelectAll() throws Exception {
        // 1. 获取Connection
        // 1.1 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));
        // 1.2 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        // 1.3 获取数据库连接 Connection
        Connection conn = dataSource.getConnection();

        // 2. 定义SQL
        String sql = "select * from tb_brand";

        // 3. 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 4. 设置参数

        // 5. 执行SQL
        ResultSet rs = pstmt.executeQuery();

        // 6. 处理结果:List 封装Brand对象,装载List集合
        List<Brand> brands = new ArrayList<>();

        while(rs.next()){
            // 获取数据
            int id = rs.getInt("id");
            String brandName = rs.getString("brand_name");
            String companyName = rs.getString("company_name");
            int ordered = rs.getInt("ordered");
            String description = rs.getString("description");
            int status = rs.getInt("status");
            // 封装Brand对象
            Brand brand = new Brand();
            brand.setId(id);
            brand.setBrandName(brandName);
            brand.setCompanyName(companyName);
            brand.setOrdered(ordered);
            brand.setDescription(description);
            brand.setStatus(status);
            // 装载集合
            brands.add(brand);
        }
        System.out.println(brands);

        // 7.释放资源
        rs.close();
        pstmt.close();
        conn.close();
    }

4.2 添加数据

/**
     * 添加
     * 1. SQL:insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?);
     * 2. 参数:需要,除了id之外的所有参数信息
     * 3. 结果:boolean
     */
    @Test
    public void testAdd() throws Exception {
        // 接收页面提交的参数
        String brandName = "香飘飘";
        String companyName = "香飘飘";
        int ordered = 1;
        String description = "绕地球一圈";
        int status = 1;

        // 1. 获取Connection
        // 1.1 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));
        // 1.2 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        // 1.3 获取数据库连接 Connection
        Connection conn = dataSource.getConnection();

        // 2. 定义SQL
        String sql = "insert into tb_brand(brand_name, company_name, ordered, description, status) values(?,?,?,?,?)";

        // 3. 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 4. 设置参数
        pstmt.setString(1,brandName);
        pstmt.setString(2,companyName);
        pstmt.setInt(3,ordered);
        pstmt.setString(4,description);
        pstmt.setInt(5,status);

        // 5. 执行SQL
        int count = pstmt.executeUpdate(); // 影响的行数

        // 6. 处理结果
        System.out.println(count > 0);

        // 7.释放资源
        pstmt.close();
        conn.close();
    }

4.3 修改数据

    /**
     * 修改
     * 1. update tb_brand
               set brand_name  = ?,
               company_name= ?,
               ordered     = ?,
               description = ?,
               status      = ?
           where id = ?

     * 2. 参数:需要,所有数据
     * 3. 结果:boolean
     */
    @Test
    public void testUpdate() throws Exception {
        // 接收页面提交的参数
        String brandName = "香飘飘";
        String companyName = "香飘飘";
        int ordered = 1000;
        String description = "绕地球三圈";
        int status = 1;
        int id = 4;

        // 1. 获取Connection
        // 1.1 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));
        // 1.2 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        // 1.3 获取数据库连接 Connection
        Connection conn = dataSource.getConnection();

        // 2. 定义SQL
        String sql = "update tb_brand\n" +
                "               set brand_name  = ?,\n" +
                "               company_name= ?,\n" +
                "               ordered     = ?,\n" +
                "               description = ?,\n" +
                "               status      = ?\n" +
                "           where id = ?";

        // 3. 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 4. 设置参数
        pstmt.setString(1,brandName);
        pstmt.setString(2,companyName);
        pstmt.setInt(3,ordered);
        pstmt.setString(4,description);
        pstmt.setInt(5,status);
        pstmt.setInt(6,id);

        // 5. 执行SQL
        int count = pstmt.executeUpdate(); // 影响的行数

        // 6. 处理结果
        System.out.println(count > 0);

        // 7.释放资源
        pstmt.close();
        conn.close();
    }

4.4 删除数据

    /**
     * 删除
     * 1. SQL:delete from tb_brand where id = ?
     * 2. 参数:需要,id
     * 3. 结果:boolean
     */
    @Test
    public void testDelete() throws Exception {
        // 接收页面提交的参数
        int id = 4;

        // 1. 获取Connection
        // 1.1 加载配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("src/druid.properties"));
        // 1.2 获取连接池对象
        DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);
        // 1.3 获取数据库连接 Connection
        Connection conn = dataSource.getConnection();

        // 2. 定义SQL
        String sql = "delete from tb_brand where id = ?";

        // 3. 获取pstmt对象
        PreparedStatement pstmt = conn.prepareStatement(sql);

        // 4. 设置参数
        pstmt.setInt(1,id);

        // 5. 执行SQL
        int count = pstmt.executeUpdate(); // 影响的行数

        // 6. 处理结果
        System.out.println(count > 0);

        // 7.释放资源
        pstmt.close();
        conn.close();
    }

你可能感兴趣的:(学习,java,mysql)