JDBC(Java DataBase Connective)

JDBC(Java DataBase Connective)

Java连接数据库的规范 - 接口

Connection - 连接

            // 1.导入jar包
            /* 2.加载驱动
            可能产生异常: ClassNotFoundException
            原因: 1.没有导入jar包
                 2.类名写错
            */
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 3.获得连接对象 DriverManager
            /* DriverManager 提供了一个静态方法 getConnection
               参数1: 连接数据库的url地址
                     jdbc:mysql://ip:port/dataBase?serverTimezone=GMT
               参数2: 连接数据库的账号
               参数3: 连接数据库的密码

               可能产生异常: SQLException
                 1.dataBase 指定错误
                 2.账号/密码错误
                 3.端口错误 -> Connection refused
                 4.ip错误 -> Network is unreachable
                 5.jdbc:mysql 错误 -> No suitable driver
                   结论: 连接数据库url需要匹配合适的驱动类
             */
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db_day01?serverTimezone=GMT", "root", "aaa");
            // 4.获得操作数据库的Statement对象 - 执行sql语句
            Statement stmt = conn.createStatement();
            // 5.执行sql语句  DDL DML DQL
            String sql = "create table u (id int primary key, name varchar(20))";
            stmt.execute(sql);
            // 6.释放资源
            stmt.close();
            conn.close();

执行sql语句的方法有三个

  • boolean execute(String sql)
    DDL DML - 返回 false
    DQL - 返回true
    因为DML 和 DQL有专门的执行方法, 所以该方法通常用来执行DDL
    返回值:有没有结果
            Statement stmt = conn.createStatement();
            // 执行DDL
            String sql = "create table u1 (id int primary key, name varchar(20))";
            boolean b = stmt.execute(sql); // false
            Statement stmt = conn.createStatement();
            // 执行DML
            String sql = "insert into u values(1, 'lucy')";
            boolean b = stmt.execute(sql); // false
            Statement stmt = conn.createStatement();
            // 执行DQL
            String sql = "select * from u ";
            boolean b = stmt.execute(sql); // true
  1. int executeUpdate(String sql)
    只能执行 DML
    返回值:影响了几行
            Statement stmt = conn.createStatement();
            // 执行DML
            String sql = "insert into u values(2, 'tom')";
            int i = stmt.executeUpdate(sql); // 1
  1. ResultSet executeQuery(String sql)
    只能执行 DQL
    返回值:查询出来的结果集
            Statement stmt = conn.createStatement();
            // 执行DQL
            String sql = "select id i, name from u ";
            ResultSet rs = stmt.executeQuery(sql); // 返回结果集 
            while (rs.next()) {
                // ResultSet获得的数据 就是当前指针位置这一行的数据
                // 获得列名为 i 的值   下标从1开始
                int id1 = rs.getInt("i");
                String name1 = rs.getString("name");
                System.out.println(id1 + " -- " + name1);
            }

PreparedStatement

  1. PreparedStatement extends Statement

  2. 预编译(sql就是一个半成品 - [? 占位符])
    例: select * from user where name = ? and password = ?
    执行sql语句:给占位符传参

  3. PreparedStatement 可以有效防止SQL注入 (重点)
    SQL注入:通过字符串的拼接, 将整个SQL语句的语义结构改变了, 从而达到一定目的(不安全的语法, 一定要避免)
    例:
    SQL语句:
    select * from user
    where name = ‘111’ and password = ‘a’
    or ‘1’=‘1’

  4. 当多次执行相同的/相似的SQL, 只需要预编译一次
    而Statement需要编译多次, PreparedStatement效率更高

  5. 批量执行(了解)

        String sql = "insert into user values(null,?,?,?,?)";
        // 预编译SQL, 一次
        PreparedStatement stmt = conn.prepareStatement(sql);
        for (int i = 0; i < 10; i++) {
            stmt.setString(1, "ww"+i);
            stmt.setInt(2, 28);
            stmt.setString(3, "2020-08-01");
            stmt.setString(4, "123");

            // 不马上执行SQL
            // 添加到SQL执行的队列中
            stmt.addBatch();
        }

        // 批量执行SQL队列中所有的语句
        stmt.executeBatch();
        // 清空之前的执行队列
        stmt.clearBatch();

JDBC事务
绑定在连接对象上的,都是默认自动提交

  • 设置事务手动提交
    conn.setAutoCommit(false)
  • 代码正常结束,提交事务
    conn.commit();
  • 代码出现异常,回滚事务(一般放在异常中)
    conn.rollback()
  • 了解
    保存事务结点
    SavePoint a = conn.setSavePoint()
    回滚到指定的结点
    conn.rollback(a)

注:mysql数据库 插入时间,可以是一个字符串

一般将创建连接和关闭连接 封装在一个工具类中 、把信息存在配置文件中(重点)

/*
   工具类的封装
 */
public class JDBCUtils {
    private static String driver ;
    private static String url ;
    private static String user ;
    private static String password ;
    static {
        // 读取属性集文件
        Properties pro = new Properties();
        try {
            pro.load(JDBCUtils.class.getResourceAsStream("db.properties"));
            driver = pro.getProperty("driver");
            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection() {
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url, user, password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }
    // 关闭连接
    public static void close(ResultSet rs, Statement stmt, Connection conn) {
        try {
            // 避免空指针
            if (rs != null) {
                rs.close();
            }
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    // 关闭连接(重载)
    public static void close(Statement stmt, Connection conn) {
        try {
            // 避免空指针
            if (stmt != null) {
                stmt.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

简单登录案例:

public class LoginDemo {
    public static void main(String[] args) {
        // 1.控制台输入账号密码
        Scanner console = new Scanner(System.in);
        System.out.println("请输入账号:");
        String username = console.nextLine();
        System.out.println("请输入密码:");
        String password = console.nextLine();

        // 2.调用登录方法
        User user = login(username, password);

        if (user == null) {
            System.out.println("用户名/密码错误!");
        } else {
            System.out.println(user.getName() + "欢迎你!");
        }
    }
    public static User login(String username, String password) {
        // 2.封装一个sql语句
        String sql = "select * from user where name = ? and password = ?";

        // 3.连接数据库, 查询 executeQuery
        Connection conn = JDBCUtils.getConnection();
        try {
            // 获得预编译的执行sql的对象
            PreparedStatement pstmt = conn.prepareStatement(sql);
            // 预编译执行对象 执行sql语句之前传入参数
            pstmt.setString(1, username);
            pstmt.setString(2, password);
            ResultSet rs = pstmt.executeQuery();
            // 4.ResultSet
            // 有没有登录成功 next() 是true - 成功
            if (rs.next()) {
                User user = new User();
                user.setId(rs.getInt("id"));
                user.setName(rs.getString("name"));
                user.setAge(rs.getInt("age"));
                user.setBirthday(rs.getDate("birthday"));
                user.setPassword(rs.getString("password"));
                return user;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        // 抛出异常
        return null;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值