二、MySQL学习 | JDBC【3】

1.JDBC(重点)

1.1 数据库驱动
驱动: 程序会通过驱动操作数据库
1.2 JDBC
SUN 公司为了简化开发人员的操作, 对数据库的操作提供了统一的Java操作数据库的规范, 简称JDBC
这些规范的实现由具体的厂商去做.
对于开发人员来说, 只需要掌握JDBC的操作即可.

java.sql
javax.sql
还需要导入一个数据库驱动包. 到MySQL官网下载在这里插入图片描述
1.3 第一个JDBC程序

创建测试数据库

1.创建一个普通项目

package lesson01;

import java.sql.*;

public class JdbcFirstLesson {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        // 1. 加载驱动
        Class.forName("com.mysql.jdbc.Driver"); // 固定写法, 加载驱动
        // 2. 用户信息和url
        // useUnicode=true&characterEncoding=utf8&useSSL=true 使用编码,使用什么编码,使用安全的连接
        // MySQL8.0 url后面要加时区serverTimezone = UTC
        String url = "jdbc:mysql://localhost:3306/"+"school"+"?useUnicode=true&characterEncoding=utf8&useSSL=false";
        String username = "root";
        String password = "liver1225";
        // 3. 连接成功, 数据库对象 Connection 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);

        // 4. 执行 SQL的 读写对象 Statement
        Statement statement = connection.createStatement();

        // 5. 对象去执行SQL, 可能存在结果, 查看
        String sql = "Select * from student";

        ResultSet resultSet = statement.executeQuery(sql); // 返回的结果结合, 封装了全部的查询结果

        while( resultSet.next()){
            System.out.println("id="+resultSet.getObject("id"));
            System.out.println("name="+resultSet.getObject("name"));
            System.out.println("birthday="+resultSet.getObject("birthday"));
            System.out.println("=================================================");
        }

        // 6. 释放连接 倒着来
        resultSet.close();
        statement.close();
        connection.close();

    }
}

步骤总结:

  1. 加载驱动 Class.ForName
  2. 连接数据库 DriverManager
  3. 获得执行sql的对象 statement(unsafe)
  4. 获得返回的结果集(查询)
  5. 释放连接

DriverManager

// 1. 加载驱动
   //DriverManager.registerDriver(new com.mysql.jdbc.Driver()); // 不推荐
   Class.forName("com.mysql.jdbc.Driver"); // 固定写法, 加载驱动
   // connection 代表数据库
   Connection connection = DriverManager.getConnection(url, username, password);

   // 事务回滚  
   // 事务提交	
   // 数据库设置自动提交
      
   connection.rollback();
   connection.commit();
   connection.setAutoCommit(true);

URL

        String url = "jdbc:mysql://localhost:3306/"+"school"+"?useUnicode=true&characterEncoding=utf8&useSSL=false";
// mysql --3306
//jdbc:mysql://主机地址:端口号//数据库名?参数名?参数1&参数2&参数3

Statement 执行SQL的对象, prepareStatement 执行SQL的对象

 // 编写SQL
  statement.executeQuery(); // 查询操作返回 ResultSet
  statement.execute(); // 执行任何SQL
  statement.executeUpdate(); // 更新, 插入, 删除. 都是用这个, 返回一个受影响的行数

ResultSet 查询的结果集: 封装了所有的查询结果

获得指定的数据类型

 resultSet.getObject(); // 在不知指定类型的情况下
 // 在知道指定类型的情况下
 resultSet.getString();
 resultSet.getInt();
 resultSet.getFloat();
 resultSet.getDate();
 resultSet.getObject();

遍历.指定

resultSet.beforeFirst();// 移动到最前面
resultSet.afterLast();// 移动到最后面
resultSet.next();// 移动到下一个 数据
resultSet.previous();// 移动到前一行 数据
resultSet.absolute();// 移动到指定行

释放资源

  // 6. 释放连接 倒着来
resultSet.close();
statement.close();
connection.close();

1.4 Statement
在这里插入图片描述

CRUD操作-create
在这里插入图片描述

CRUD操作-delete
在这里插入图片描述

CRUD操作-update
在这里插入图片描述

CRUD操作-query

在这里插入图片描述
executeQuery更好

代码实现:
提取工具类

package lesson02.utils;

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

public class JdbcUtils {

    private static String driver = null;
    private static String url = null;
    private static String username = null;
    private static String password = null;

    static {
        try{
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); // 输入流
            Properties properties = new Properties();
            properties.load(in); // 加载属性

            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //1.驱动只用加载一次
            Class.forName(driver);

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    // 获取连接
    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) {
                throw new RuntimeException(e);
            }
        }
        if(st!=null){
            try {
                st.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

}

2.编写增删改的方法, executeUpdate

// 增
package lesson02;

import lesson02.utils.JdbcUtils;

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

public class TestInsert {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            st = conn.createStatement();// 获得sql的执行对象
            String sql = "Insert Into student(id, `name`, `birthday`)" + "Values(4, 'ch', '1998-06-06 19:46:22.0')";

            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("insert success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn,st, rs);
        }



    }
}

// 删
package lesson02;

import lesson02.utils.JdbcUtils;

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

public class TestDelete {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            st = conn.createStatement();// 获得sql的执行对象
            String sql = "Delete From student Where id = 4";

            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("delete success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn,st, rs);
        }



    }
}

// 改
package lesson02;

import lesson02.utils.JdbcUtils;

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

public class TestUpdate {
    public static void main(String[] args) throws SQLException {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            st = conn.createStatement();// 获得sql的执行对象
            String sql = "Update student Set `name`='ch',`birthday`='1998-06-05 19:46:22.0' where id=1";

            int i = st.executeUpdate(sql);
            if(i>0){
                System.out.println("update success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn,st, rs);
        }



    }
}

//查
package lesson02;

import lesson02.utils.JdbcUtils;

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

public class TestSelect {

    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();

            // SQL
            String sql = "Select * From student Where id = 1";

            rs = st.executeQuery(sql); //查询 完毕 会返回结果集

            while(rs.next()){
                System.out.println(rs.getString("name"));

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

SQL注入的问题

sql存在问题, 会被攻击导致数据泄露 sql会被拼接 or
指web应用对用户输入数据的合法性没有判断或过滤不严.

package lesson02;

import lesson02.utils.JdbcUtils;

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

public class SQLzhuru {
    public static void main(String[] args) {
//        login("ch", "1"); // 正常指令
        login(" 'or '1=1", " 'or '1=1"); // 攻击注入
    }

    // 登录业务
    public static void login(String username, String password) {
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();
            st = conn.createStatement();

            // SQL
            String sql = "Select * From student Where `name`= '" + username + "' AND `id`='" + password + "'";

            rs = st.executeQuery(sql); //查询 完毕 会返回结果集

            while (rs.next()) {
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("id"));
                System.out.println("==============================");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JdbcUtils.release(conn, st, rs);
        }
    }
}

1.5 PreparedStatement 对象

它可以防止SQL注入, 并且效率更高!
1)增

package lesson03;

import lesson02.utils.JdbcUtils;

import java.sql.*;

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接

            // 区别
            String sql = "Insert Into student(id, `name`, `birthday`)" + "Values(?, ?, ?)"; //使用?占位符代替参数

            pst = conn.prepareStatement(sql);// 预编译sql, 先写sql, 如然后不执行

            // 手动给参数赋值
            pst.setInt(1, 3); // id
            pst.setString(2, "wzc"); // name
            // 注意点: sql.Date 和 utils.Date
            pst.setDate(3, new java.sql.Date(new java.util.Date().getTime())); // birthday


            int i = pst.executeUpdate(); // 已经预编译过了
            if(i>0){
                System.out.println("insert success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn, pst, null);
        }

    }
}

2)删

package lesson03;

import lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接

            // 区别
            String sql = "Delete From student Where id = ?"; //使用?占位符代替参数

            pst = conn.prepareStatement(sql);// 预编译sql, 先写sql, 如然后不执行

            // 手动给参数赋值
            pst.setInt(1, 3); // id

            int i = pst.executeUpdate(); // 已经预编译过了
            if(i>0){
                System.out.println("delete success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn, pst, null);
        }

    }
}

3)改

package lesson03;

import lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestUpdate {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接

            // 区别
            String sql = "Update student Set `name`=?,`birthday`=? where id=?"; //使用?占位符代替参数

            pst = conn.prepareStatement(sql);// 预编译sql, 先写sql, 如然后不执行

            // 手动给参数赋值
            pst.setString(1, "wzc"); // name
            // 注意点: sql.Date 和 utils.Date
            pst.setDate(2, new java.sql.Date(new java.util.Date().getTime())); // birthday
            pst.setInt(3, 1); // id


            int i = pst.executeUpdate(); // 已经预编译过了
            if(i>0){
                System.out.println("update success!");
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn, pst, null);
        }

    }
}

4)查

package lesson03;

import lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接

            // 区别
            String sql = "Select * From student Where id = ?"; //使用?占位符代替参数
            pst = conn.prepareStatement(sql);// 预编译sql, 先写sql, 如然后不执行
            // 手动给参数赋值
            pst.setInt(1, 1); // id

            rs = pst.executeQuery();

            while(rs.next()){
                System.out.println(rs.getString("name"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            JdbcUtils.release(conn, pst, null);
        }

    }
}

5)防止sql注入

package lesson03;

import lesson02.utils.JdbcUtils;

import java.sql.*;

public class SQLzhuru {
    public static void main(String[] args) {
//        login("wzc", "1"); // 正常指令
        login(" '' or 1=1", " '' or 1=1"); // 攻击注入, 此时就不会报错了
    }

    // 登录业务
    public static void login(String username, String password) {
        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            conn = JdbcUtils.getConnection();

            // SQL 防止注入攻击的本质, 把传递进来的参数当成字符
            // 假设其中存在转义字符, 比如说' 会被直接转义.
            String sql = "Select * From student Where `name`=? and `id`=?"; //Mybatis

            pst = conn.prepareStatement(sql);
            pst.setString(1, username);
            pst.setString(2, password);


            rs = pst.executeQuery(); //查询 完毕 会返回结果集

            while (rs.next()) {
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("id"));
                System.out.println("==============================");

            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JdbcUtils.release(conn, pst, rs);
        }
    }
}

1.6 使用IDEA连接数据库

1.7 事务
要么都成功,要么都失败

ACID原则

代码实现

package lesson04;

import lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class TestTransaction {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement pst = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection(); // 获取数据库连接
            // 关闭自动提交==开启事务
            conn.setAutoCommit(false);

            String sql1 = "Update account set money=money-100 where NAME = 'A'";
            pst = conn.prepareStatement(sql1);
            pst.executeUpdate();

//            int x = 1/0; // 失败语句

            String sql2 = "Update account set money=money+100 where NAME = 'B'";
            pst = conn.prepareStatement(sql2);
            pst.executeUpdate();

            // 业务完毕, 提交事务
            conn.commit();
            System.out.println("成功");

            } catch (SQLException e) {
                try{
                    conn.rollback(); // 失败了会回滚, 但是默认就是会回滚的
                }catch (SQLException e1){
                    e1.printStackTrace();
                } throw new RuntimeException(e);
                } finally {
                    JdbcUtils.release(conn, pst, rs);
                }
    }
}

关键语句:
1.开启事务 conn.setAutoCommmit(false);
2.一组业务执行完毕, 提交事务
3.可以在catch语句中显式得定义 回滚语句, 但默认失败会回滚

1.8 数据库连接池

数据库连接—执行完毕—释放
连接—释放 十分浪费系统资源

池化技术:准备一些预先的资源, 先连接预先准备好的

编写连接池,只需要实现一个接口:DataSource

开源数据源实现

DBCP
C3P0
Druid:阿里巴巴,已放弃
使用了这些数据库连接池后, 就不需要编写连接数据库的代码

DBCP

需要用到的jar包:commons-dbcp-1.4

C3P0

导如jar包即可.

结论: 无论使用什么数据源, 本质还是一样的. 接口DataSource不会变

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值