Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)

1 JDBC(Java Database Connectivity)

1.1 JDBC概念

JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作

1.2 JDBC 核心思想

Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。

JDBC核心思想


2 JDBC开发步骤
/**
 * JDBC的开发步骤:
 *    0、准备工作
 *         a、准备数据库和数据表
 *         b、导入jar包
 *            1、在工程下新建一个lib的文件,将驱动jar包放入到文件夹中 
 *            2、右击jar包---> add as library
 *                  注意:类路径(classpath) 就是java代码生成.class文件的路径
 *    1、注册驱动
 *    2、获取数据库连接对象Connection
 *    3、获取数据库操作对象
 *    4、通过数据库操作对象执行SQL语句
 *    5、处理结果
 *    6、释放资源
 */

2.0 环境准备

环境准备

  • a、将数据库连接驱动包赋值到当前工程的lib文件夹下
  • b、将jar包添加到类路径(class文件生成的位置)中。右击jar包 —> add as library

2.1 注册数据库驱动

//1、注册数据库驱动
//实现方式一:不推荐使用
//Driver driver = new Driver();
//DriverManager.registerDriver(driver);
//实现方式二:推荐使用
Class.forName("com.mysql.jdbc.Driver");//主动触发类加载,执行静态代码块,进而注册驱动

2.2 获取数据库的连接

协议://地址:端口号

  • mysql 5.7版本 jdbc:mysql://localhost:3306/数据库名
  • mysql 8.x版本 需要加上指定时区 jdbc:mysql://localhost:3306/数据库名?serverTimezone=?serverTimezone = UTC (北京时间)
  • jdbc:mysql://localhost:3306/数据库名?serverTimezone=?serverTimezone = Asia/shanghai (j精确到时分秒时间)
  • 本机数据库localhost:3306可以省略不写,即 jdbc:mysql:///数据库名
 // 2、获取数据库连接对象Connection
/**
 * 网络编程三要素
 *      协议+地址+端口
 *      jdbc:mysql://localhost:3306/数据库名?serverTimezone=UTC
 */      
Connection conn = 
    DriverManager.getConnection("jdbc:mysql://localhost:3306/java2303", "root", "123456");

2.3 获取数据库操作对象Statement

// 3、获取数据库操作对象
Statement statement = conn.createStatement();

2.4 通过Statement对象执行SQL语句

// 4、通过数据库操作对象执行SQL语句
int count = statement.executeUpdate(
    "insert into emp (empno,ename,job,mgr,hiredate,sal,comm,deptno) 
    values (6666,'张三','java',7369,'2021-05-01',30000,200,30)");

2.5 处理返回结果

// 5、处理结果
if(count > 0){
    System.out.println("插入成功!!");
}else{
    System.out.println("插入失败!!");
}

2.6 释放资源

//6、释放资源
statement.close();
conn.close();

3 ResultSet结果集

//5、处理结果集
/**
 * ResultSet提供了一组方法
 *          next(); 判断是否有下一行数据,如果有返回true,并将游标移动到下一行
 *          getXXX("字段名");    XXX表示字段在java中的对应的类型
 *          getXXX(列的下标);    XXX表示字段在java中的对应的类型
 */

3.1 查询案例

查询emp表的数据

while(rs.next()){
    int empno = rs.getInt("empno");
    //int empno = rs.getInt(1);
    System.out.println(empno);
    String ename = rs.getString("ename");
    System.out.println(ename);
    String job = rs.getString("job");
    System.out.println(job);
    Date hiredate = rs.getDate("hiredate");
    System.out.println(hiredate);
    double sal = rs.getDouble("sal");
    System.out.println(sal);
}

四、综合案例【登录】

4.1 登录分析

/**
 * 登录的思路:
 *      1、根据用户输入的用户名和密码到数据库中查询
 *          select * from tb_user where username = "你输入的用户名" and password = "你输入的密码"
 *          select * from tb_user where username = admin and password = 123
 *          如果有结果:登录成功
 *          如果没有结果:登录失败
 */

4.2 登录案例实现

public class JDBCDemo05 {    
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();
        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = 
            DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");
        Statement statement = conn.createStatement();
        String sql = " select * from tb_user where username = '" + 
            username + "' and password = '" + password +"'";
        System.out.println(sql);
        ResultSet rs = statement.executeQuery(sql);
        if(rs.next()){
            //登录成功
            System.out.println("登录成功");
        }else{
            //登录失败
            System.out.println("登录失败");
        }
        rs.close();
        statement.close();
        conn.close();
    }
}

4.3 登录案例分析-SQL注入问题

以上代码会出现SQL注入问题

  • 用户输入的数据中有 SQL 关键字或语法并且参与了 SQL 语句的编译,导致 SQL 语句编译后的条件含义为 true,一直得到正确的结果。这种现象称为 SQL 注入。
  • 字符串的拼接操作也是非常的不方便

4.4 登录案例更新

public class JDBCDemo06 {
    public static void main(String[] args) throws Exception {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();

        Class.forName("com.mysql.jdbc.Driver");
        Connection conn = 
            DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");
        //3、获取数据库操作对象PreparedStatement    预加载SQL语句
        PreparedStatement ps =
            conn.prepareStatement("select * from tb_user where username = ? and password = ?");
        //3.1 设置占位符的值
        /**
         *  PreparedStatement对象中提供了一组方法
         *      setXXX(index从1开始,要传入的值)    XXX表示对应的java类型
         */
        ps.setString(1,username);
        ps.setString(2,password);
        System.out.println(ps);
        //4、执行SQL语句
        ResultSet rs = ps.executeQuery();
        if(rs.next()){
            //登录成功
            System.out.println("登录成功");
        }else{
            //登录失败
            System.out.println("登录失败");
        }
        rs.close();
        ps.close();
        conn.close();
    }
}

4.5 PreparedStatement

PreparedStatement 继承了 Statement 接口,执行 SQL 语句的方法无异。

作用:

  • 预编译SQL 语句,效率高。
  • 安全,避免SQL注入

五、ORM映射

5.1 思想

ORM (Object Relational Mapping)

将数据库中的表的数据,一行一行的映射到Java对象中

ORM思想

image.png

5.2 实体类的规范

JavaBean设计规范

1、类名与表名一致,属性名和字段名一致

2、私有化属性对外提供set、get方法

3、提供有参和无参构造

4、基本数据类型要使用包装类(默认值)

5、在需要的时候实现序列化接口

5.3 代码实现

查询

public class JDBCDemo04 {
    public static void main(String[] args) throws Exception {
        //1、注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2、获取数据库连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql:///java2303", "root", "123456");
        //3、获取数据库操作对象
        Statement statement = conn.createStatement();
        //4、执行SQL语句
        ResultSet rs = statement.executeQuery("select * from emp");
        //5、处理结果集
        //定义List集合保存所有的emp对象
        List<Emp> empList = new ArrayList<>();
        while(rs.next()){
            int empno = rs.getInt("empno");
            String ename = rs.getString("ename");
            String job = rs.getString("job");
            int mgr = rs.getInt("mgr");
            Date hiredate = rs.getDate("hiredate");
            double sal = rs.getDouble("sal");
            double comm = rs.getDouble("comm");
            int deptno = rs.getInt("deptno");
            //将查询的结果存放到Emp对象中
            Emp emp = new Emp(empno,ename,job,mgr,hiredate,sal,comm,deptno);
            //将Emp对象添加到List中
            empList.add(emp);
        }
        //遍历集合中所有元素
        empList.forEach(System.out::println);
//        for(Emp emp : empList){
//            System.out.println(emp);
//        }
        //6、释放资源
        rs.close();
        statement.close();
        conn.close();
    }
}

6 封装工具类

1、注册数据库驱动(静态代码块)

2、获取数据库连接 (方法:getConnection)

3、释放资源 (方法:closeAll(Connection , Statement , ResultSet ))

4、将配置信息放到properties配置文件中,减少硬编码

6.1 代码实现

工具类代码

/**
* 数据库工具类
 */
public class JDBCUtils {
    /**
     * 1、注册驱动(只需要注册一次)
     *      可以将注册驱动的代码写到静态代码块中
     * 2、获取数据库连接
     *      提供静态一个方法,用于返回数据库连接对象
     * 3、关闭资源
     *      提供静态一个方法,用于释放资源
     * 4、硬编码问题(.xml  .properties)
     *      将数据源信息保存到配置文件中,然后在代码中进行读取
     *      properties文件的格式:key和value都是String类型
     *              key=value
     */
    private static String driver;
    private static String url;
    private static String username;
    private static String password;
    static{
        try {
            //读取配置文件
            Properties properties = new Properties();
            //通过类对象读取当前类路径下的资源
            InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //将配置文件中的信息读取到Properties集合中
            properties.load(in);
            //从集合中取出数据
            driver = properties.getProperty("driver123");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //注册驱动
            Class.forName(driver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection conn = null;
        try {
            conn = DriverManager.getConnection(url,username,password);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        return conn;
    }

    public static void closeAll(Connection conn, Statement statement, ResultSet rs){
        try {
            if(rs!=null)
                rs.close();
            if(statement != null)
                statement.close();
            if(conn != null)
                conn.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}


编写配置文件properties (集合工具类-自己补充)

  • 在src更目录下创建xx.properties的new file
  • 集合键值对 driver = com.mysql.jdbc.Driver url = username = password =
  • 在静态代码块读取配置文件
  1. 创建properties对象

配置文件 db.properties

driver123=com.mysql.jdbc.Driver
url=jdbc:mysql:///java2303
username=root
password=123456

6.2 工具类测试

public class JDBCDemo01 {
    public static void main(String[] args) throws SQLException {
        //2、获取数据库连接
        Connection conn = JDBCUtils.getConnection();
        //3、获取数据库操作对象
        PreparedStatement ps = conn.prepareStatement("select * from emp");
        //4、执行SQL语句
        ResultSet rs = ps.executeQuery();
        //5、处理结果集
        while(rs.next()){
            int empno = rs.getInt("empno");
            String ename = rs.getString("ename");
            String job = rs.getString("job");
            int mgr = rs.getInt("mgr");
            Date hiredate = rs.getDate("hiredate");
            double sal = rs.getDouble("sal");
            double comm = rs.getDouble("comm");
            int deptno = rs.getInt("deptno");
            System.out.println(ename);
        }
        //6、释放资源
        JDBCUtils.closeAll(conn,ps,rs);
    }
}

7 DAO (Data Access Object)

DAO 实现了业务逻辑与数据库访问相分离。

  • 对同一张表的所有操作封装在XxxDaoImpl对象中。
  • 根据增删改查的不同功能实现具体的方法(insert、update、delete、select、selectAll)。

7.1 开发流程

7.1.1 EmpDao接口

public interface EmpDao {
    //增加员工
    int insertEmp(Emp emp) throws SQLException;
    //删除员工
    int deleteEmp(int empno);
    //修改员工
    int updateEmp(Emp emp) throws SQLException;
    //查询所有员工
    List<Emp> selectAll() throws SQLException;
    //查询单个员工
    Emp selectOne(int empno);
}

7.1.2 实体类

com.qf.pojo包下创建实体类

public class Emp {
   private Integer empno;
   private String ename;
   private String job;
   private Integer mgr;
   private Date hiredate;
   private Double sal;
   private Double comm;
   private Integer deptno;
    //省略get、set、构造方法
}

7.1.3 EmpDao实现类

public class EmpDaoImpl implements EmpDao {
    @Override
    public int insertEmp(Emp emp) throws SQLException {
        //2、获取数据库连接对象
        Connection conn = JDBCUtils.getConnection();
        //3、获取数据库操作对象
        PreparedStatement ps = conn.prepareStatement("insert into emp values(?,?,?,?,?,?,?,?)");
        //3.1设置占位符的值
        ps.setInt(1,emp.getEmpno());
        ps.setString(2,emp.getEname());
        ps.setString(3,emp.getJob());
        ps.setInt(4,emp.getMgr());
        //将util.date 转换成 sql.date
        ps.setDate(5,new Date(emp.getHireadate().getTime()));
        ps.setDouble(6,emp.getSal());
        ps.setDouble(7,emp.getComm());
        ps.setInt(8,emp.getDeptno());
        //4、执行SQL语句
        int count = ps.executeUpdate();
        //5、处理结果
        //6、释放资源
        JDBCUtils.closeAll(conn,ps,null);
        return count;
    }

    @Override
    public int deleteEmp(int empno) {
        return 0;
    }

    @Override
    public int updateEmp(Emp emp) throws SQLException {
        //2、获取数据库连接对象
        Connection conn = JDBCUtils.getConnection();
        //3、获取数据库操作对象
        PreparedStatement ps = conn.prepareStatement("update emp set ename=?,job=?,mgr=?,hiredate=?,sal=?,comm=?,deptno=? where empno = ?");
        //3.1设置占位符的值
        ps.setString(1,emp.getEname());
        ps.setString(2,emp.getJob());
        ps.setInt(3,emp.getMgr());
        //将util.date 转换成 sql.date
        ps.setDate(4,new Date(emp.getHireadate().getTime()));
        ps.setDouble(5,emp.getSal());
        ps.setDouble(6,emp.getComm());
        ps.setInt(7,emp.getDeptno());
        ps.setInt(8,emp.getEmpno());
        //4、执行SQL语句
        int count = ps.executeUpdate();
        //5、处理结果
        //6、释放资源
        JDBCUtils.closeAll(conn,ps,null);
        return count;
    }

    @Override
    public List<Emp> selectAll() throws SQLException {
        //2、获取数据库连接对象
        Connection conn = JDBCUtils.getConnection();
        //3、获取数据库操作对象
        PreparedStatement ps = conn.prepareStatement("select * from emp");
        //4、执行SQL语句
        ResultSet rs = ps.executeQuery();
        //5、处理结果集
        List<Emp> empList = new ArrayList<>();
        while(rs.next()){
            int empno = rs.getInt("empno");
            String ename = rs.getString("ename");
            String job = rs.getString("job");
            int mgr = rs.getInt("mgr");
            Date hiredate = rs.getDate("hiredate");
            double sal = rs.getDouble("sal");
            double comm = rs.getDouble("comm");
            int deptno = rs.getInt("deptno");
            //将查询的结果存放到Emp对象中
            Emp emp = new Emp(empno,ename,job,mgr,hiredate,sal,comm,deptno);
            //将Emp对象添加到List中
            empList.add(emp);
        }
        //6、释放资源
        JDBCUtils.closeAll(conn,ps,rs);
        return empList;
    }

    @Override
    public Emp selectOne(int empno) {
        return null;
    }
}

7.1.4 测试类

public class TestEmpDao {
    public static void main(String[] args) throws Exception {
        //测试查询所有
//        EmpDao empDao = new EmpDaoImpl();
//        List<Emp> empList = empDao.selectAll();
//        System.out.println(empList);
        
        //测试增加
//        EmpDao empDao = new EmpDaoImpl();
//        Emp emp = new Emp(9000,"韩梅梅","mysql",7369,new Date(),4000d,200d,30);
//        System.out.println(empDao.insertEmp(emp));

        //测试修改
        EmpDao empDao = new EmpDaoImpl();
        Emp emp = new Emp(9000,"李雷","java",7369,new Date(),40000d,200d,30);
        System.out.println(empDao.updateEmp(emp));
    }
}

Java数据库部分(MySQL+JDBC)(二、JDBC超详细学习笔记)(下):https://developer.aliyun.com/article/1580599

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
3天前
|
存储 关系型数据库 MySQL
【Java面试题汇总】MySQL数据库篇(2023版)
聚簇索引和非聚簇索引、索引的底层数据结构、B树和B+树、MySQL为什么不用红黑树而用B+树、数据库引擎有哪些、InnoDB的MVCC、乐观锁和悲观锁、ACID、事务隔离级别、MySQL主从同步、MySQL调优
【Java面试题汇总】MySQL数据库篇(2023版)
|
4天前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
从Java环境的搭建到实际代码的编写,从基本用法的讲解到底层原理的剖析,深度解析Java基础知识。本文是《Java学习路线》专栏的起始文章,旨在提供一套完整的Java学习路线,覆盖Java基础知识、数据库、SSM/SpringBoot等框架、Redis/MQ等中间件、设计模式、架构设计、性能调优、源码解读、核心面试题等全面的知识点,并在未来不断更新和完善,帮助Java从业者在更短的时间内成长为高级开发。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(基础篇)
|
4天前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
本文是Java基础的进阶篇,对异常、集合、泛型、Java8新特性、I/O流等知识进行深入浅出的介绍,并附有对应的代码示例,重要的地方带有对性能、底层原理、源码的剖析。适合Java初学者。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(进阶篇)
|
4天前
|
存储 安全 Java
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(高级篇)
本文是“Java学习路线”中Java基础知识的高级篇,主要对多线程和反射进行了深入浅出的介绍,在多线程部分,详细介绍了线程的概念、生命周期、多线程的线程安全、线程通信、线程同步,并对synchronized和Lock锁;反射部分对反射的特性、功能、优缺点、适用场景等进行了介绍。
Java修仙之路,十万字吐血整理全网最完整Java学习笔记(高级篇)
|
16天前
|
自然语言处理 算法 Java
Java如何判断两句话的相似度类型MySQL的match
【9月更文挑战第1天】Java如何判断两句话的相似度类型MySQL的match
18 2
|
19天前
|
jenkins Java Shell
jenkins学习笔记之十三:配置SonarScanner扫描Java项目
jenkins学习笔记之十三:配置SonarScanner扫描Java项目
|
2天前
|
存储 SQL 关系型数据库
使用MySQL Workbench进行数据库备份
【9月更文挑战第13天】以下是使用MySQL Workbench进行数据库备份的步骤:启动软件后,通过“Database”菜单中的“管理连接”选项配置并选择要备份的数据库。随后,选择“数据导出”,确认导出的数据库及格式(推荐SQL格式),设置存储路径,点击“开始导出”。完成后,可在指定路径找到备份文件,建议定期备份并存储于安全位置。
39 11
|
26天前
|
SQL 关系型数据库 MySQL
【揭秘】MySQL binlog日志与GTID:如何让数据库备份恢复变得轻松简单?
【8月更文挑战第22天】MySQL的binlog日志记录数据变更,用于恢复、复制和点恢复;GTID为每笔事务分配唯一ID,简化复制和恢复流程。开启binlog和GTID后,可通过`mysqldump`进行逻辑备份,包含binlog位置信息,或用`xtrabackup`做物理备份。恢复时,使用`mysql`命令执行备份文件,或通过`innobackupex`恢复物理备份。GTID模式下的主从复制配置更简便。
112 2
|
21天前
|
弹性计算 关系型数据库 数据库
手把手带你从自建 MySQL 迁移到云数据库,一步就能脱胎换骨
阿里云瑶池数据库来开课啦!自建数据库迁移至云数据库 RDS原来只要一步操作就能搞定!点击阅读原文完成实验就可获得一本日历哦~
|
25天前
|
关系型数据库 MySQL 数据库
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决
RDS MySQL灾备服务协同解决方案构建问题之数据库备份数据的云上云下迁移如何解决