Java研学-jdbc(一)

2023-12-13 09:44:41

一 概述

1 持久化概述

??持久化(persistence): 把内存中的数据保存到可掉电式存储设备 (硬盘、U盘等) 中以供之后使用。
??数据持久化是将数据保存到各种关系数据库, 而在 Java中,数据库存取技术只能通过 jdbc 来访问数据库。jdbc 是 Java 语言访问数据库的基石,其他技术都是对 jdbc 的封装.

2 JDBC 概述

??JDBC(Java DataBase Connectivity Java 数据库连接)是一种用于执行 SQL 语句的 Java API,可以为多种关系型数据库提供统一访问,它由一组用 Java 语言编写的类和接口组成。
??其实就是Java 官方提供的一套规范(接口),帮助开发人员快速实现不同关系型数据库的连接。

二 使用的功能类

1 DriverManager 类

??DriverManager:驱动管理对象,主要用于加载注册关系型数据库的 Driver 类以及获取和关系型数据库的连接对象
① 加载注册驱动

// 语法:注册给定的驱动对象
static void registerDriver(Driver driver);

// 在 com.mysql.jdbc.Driver 类中存在静态代码块,把 com.mysql.jdbc.Driver 这一份字节码加载进 JVM
// 字节码被加载进JVM,就会执行其静态代码块.而其底层的静态代码块在完成注册驱动工作,将驱动注册到DriverManger 中
static {
        try {
            DriverManager.registerDriver(new Driver());
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
}

// 加载注册驱动
Class.forName("com.mysql.jdbc.Driver");

??Java6 开始,JDBC4.0 无需加载注册驱动在 jar 包中存在一个java.sql.Driver 配置文件。此文件已经包含 com.mysql.jdbc.Driver 驱动名称。
?? 程序会自动从 META-INF/services/java.sql.Driver 去读取当前的驱动类的全限定名,故不写加载注册驱动也可以,但 web 项目必须写加载注册驱动代码,否则无法连接数据库

② 获取连接对象

// 语法:获取连接对象
static Connection getConnection(String url,String username,String password);

// 参数 url 指定连接某一个数据库的路径,语法:
url=jdbc:mysql://localhost:3306/jdbcdemo

// 若连接的是本机的 MySQL,并且端口是默认 3306 ,可以简写
url=jdbc:mysql:///jdbcdemo

// 连接数据库的账号
username
// 连接数据库的密码
password

2 Connection 类

??关系型数据库连接对象,用于 Java 程序与数据库的通信连接

// 获取执行语句对象(静态语句执行对象)
Statement createStatement();
// 获取执行语句对象(预编译语句执行对象)
PreparedStatement prepareStatement(String sql);
// 释放资源,关闭连接对象
void close();

// 设置是否为自动提交事务,setAutoCommit(boolean)默认值为true表示自动提交(每条SQL语句都是一个单独的事务),设置为false相当于开启事务
con.setAutoCommit(false) 

// 提交结束事务
commit()
// 回滚结束事务
rollback()

3 Statement 类

??静态SQL语句执行对象,用于执行字符串的 SQL 语句

// 执行DML/DDL语句,返回值为DML受影响的行数,DDL则返回0,参数为insert、update、delete、create语句
int executeUpdate(String sql);

// 执行DQL语句,返回值为执行查询之后的结果数据,参数为select 
ResuleSet executeQuery(String sql);

// 释放资源 关闭Statement对象
void close();

三 创建流程

1 创建数据库表

CREATE TABLE `t_employee` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `eid` varchar(10) NOT NULL,
  `ename` varchar(6) NOT NULL,
  `job` varchar(10) DEFAULT NULL,
  `salary` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `eid` (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

2 增加一条员工信息

public class Test {
    // 增加一条员工信息
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //1.加载jdbc注册驱动com.mysql.jdbc.Driver
        //反射加载类的字节码对象,目的是实例化Driver对象:底层调用newInstance()方法 需要目标类中包含无参构造
        Class.forName("com.mysql.jdbc.Driver");
        //2.获取数据库连接对象
        //Connection建立java代码和mysql数据库之间的连接关系
        /*
         * jdbc:mysql:// 协议 表示使用jdbc技术连接mysql数据库
         * localhost:3306/ 本机回环地址 localhost==127.0.0.1
         * 3306mysql默认的端口号
         * localhost:3306当连接本机默认mysql可以省略
         * 192.168.1.23:3307链接他人数据库的格式
         * jdbcdemo 需要连接的目标数据库名称
         * root mysql登录账号
         * root mysql登录密码
         * */
        Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/web_crud",
                "root","root");
        //3.创建执行sql语句的对象:Statement最终执行sql语句的操作者
        Statement statement= connection.createStatement();
        //4.执行目标的sql语句
        /*
         * Statement对象提供了数据库表数据的CRUD操作的方法API
         * 增删改:executeUpdate()
         * 查询:executeQuery()
         * */
        //双引号嵌套:通常会将包含的引号加转译字符或者使用单引号
        //String sql = "INSERT INTO t_employee(eid,ename,job,salary) VALUES(\"tj008\",\"大黄\",\"医药代表\",15000)";
        //单引号不转义
        String sql = "INSERT INTO t_employee(eid,ename,job,salary) VALUES('tj006','大黄','医药代表',15000)";
        int row= statement.executeUpdate(sql);
        //5.关闭对象,释放资源
        statement.close();
        connection.close();
    }
}

四 Dao组件

1 概述

??DAO(Data Access Object) 数据访问对象,即面向对象的数据库接口,将所有对数据源(数据库)的访问操作抽象封装在一个公共 API 中,实现增删改查

2 方法设计

??① 对数据库数据进行修改时,调用者需要传递多个参数进来,把这些数据存入数据库
??② 对数据库数据进行查询时,结果集的每行数据有多个列的值,把这些数据返回给调用者
??③ 需传递多个数据时,使用 JavaBean 对其进行封装

// 调用者将保存的数据封装到employee对象中,传递进来
void save(Employee ep);
// 通过id进行查询后,将每行数据封装到employee对象中,返回给调用者
Student selectOne(long id);

3 步骤

??① 创建项目,导入数据库驱动包
??② 创建表和实体类包以及实体对象 (domain/Employee)
??③ 创建 DAO 包和 DAO 接口,设计 DAO 接口方法 (dao/IEmployeeDAO)
??④ 创建 DAO 实现包,实现 DAO 接口(dao.impl/EmployeeDAOImpl)
??⑤ 创建测试目录,生成测试类和方法(test/EmployeeDAOTest)
??⑥ 书写实现,实现一个方法测试一个方法并且测试通过

4 演示

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Long id;
    private String ename;
    private String job;
    private String eid;
    private Integer salary;
}

接口

public interface IEmployeeDao {
    //修改员工
    public void updateEmployee(Employee employee);
    //增加员工
    public void addEmployee(Employee employee);
}

实现类 – 执行 SQL 需要的参数是调用者传递进来的,故需要将其拼接到 SQL 里面

public class EmployeeDaoImpl implements IEmployeeDao {
    /*修改员工*/
    @Override
    public void updateEmployee(Employee employee) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/web_crud",
                    "root","root");
            Statement statement = connection.createStatement();
            String sql="update t_employee set ename='"+employee.getEname()+"' ,job='"+employee.getJob()+"',eid='"+employee.getEid()+"',salary='"+employee.getSalary()+"' WHERE id="+employee.getId()+"";
            System.out.println(sql);
            int row = statement.executeUpdate(sql);
            statement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*增加员工*/
    @Override
    public void addEmployee(Employee employee) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/web_crud",
                    "root","root");
            Statement statement = connection.createStatement();
            String sql="insert into t_employee(ename,job,eid,salary)values('"+employee.getEname()+"','"+employee.getJob()+"','"+employee.getEid()+"','"+employee.getSalary()+"')";
            System.out.println(sql);
            int row = statement.executeUpdate(sql);
            statement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

测试类

public class EmployeeTest {
    /*修改员工信息*/
    @Test
    public void employee_update(){
        // 创建dao对象
        IEmployeeDao employeeDao=new EmployeeDaoImpl();
        // 修改1号员工信息
        employeeDao.updateEmployee(new Employee(1L,"大黄","保安","tj028",15000));
    }

    /*增加员工信息*/
    @Test
    public void employee_add() {
        IEmployeeDao employeeDao=new EmployeeDaoImpl();
        employeeDao.addEmployee(new Employee(null,"大黄","保安","tj027",15000));
    }
}

五 预编译对象

1 作用:

??PreparedStatement 接口: 是 Statement 接口的子接口, 享有 Statement 中的方法,预编译语句对象的sql 语句中使用 ? 来作为值的占位符,从而解决拼接sql字符串易出错的问题

2 优化代码

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Long id;
    private String ename;
    private String job;
    private String eid;
    private Integer salary;
}

接口

public interface IEmployeeDao {
    //修改员工
    public void updateEmployee(Employee employee);
    //增加员工
    public void addEmployee(Employee employee);
    //根据id查询员工
    public Employee queryById(int id);
    //查询所有
    public List<Employee> queryALl();
}

实现类

public class EmployeeDaoImpl implements IEmployeeDao {
    /*修改员工*/
    @Override
    public void updateEmployee(Employee employee) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
            String sql="update t_employee  set eid=? ,ename=? ,job=?,salary=? WHERE id=?";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setObject(1,employee.getEid());
            statement.setObject(2,employee.getEname());
            statement.setObject(3,employee.getJob());
            statement.setObject(4,employee.getSalary());
            statement.setObject(5,employee.getId());
            statement.executeUpdate();
            statement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*增加员工*/
    @Override
    public void addEmployee(Employee employee) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
            //创建预编译对象:sql执行对象
            //编译sql的时候使用占位符替换语句中的未知的变量值
            String sql="insert into t_employee(eid,ename,job,salary)values(?,?,?,?)";
            PreparedStatement statement = connection.prepareStatement(sql);
            /*执行CRUD操作前需通过set方法将预编译的占位符替换成客户端传入的具体值*/
            /*statement.setString(1,employee.getEid());
            statement.setInt(2,employee.getEname());
            statement.setString(3,employee.getJob());
            statement.setString(4,employee.getSalary());*/
            // 顺序与占位符顺序一致(字段类型也一致),使用setObject可不考虑字段类型
            statement.setObject(1,employee.getEid());
            statement.setObject(2,employee.getEname());
            statement.setObject(3,employee.getJob());
            statement.setObject(4,employee.getSalary());
            //执行增加操作 此时需要知道占位符的值是什么
            statement.executeUpdate();
            statement.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*根据id查询*/
    @Override
    public Employee queryById(int id) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
            String sql="SELECT * from t_employee WHERE id=?";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setObject(1,id);
            //执行查询:将查询的员工信息封装在返回结果集对象中
            ResultSet resultSet = statement.executeQuery();
            //遍历集合
            Employee employee=null;
            while (resultSet.next()){//当遍历的集合中有数据,就获取里面的信息
                //循环依次获取数据库表的一行数据
                //获取字段信息
                Long tid = resultSet.getLong("id");
                String eid = resultSet.getString("eid");
                String ename = resultSet.getString("ename");
                String job = resultSet.getString("job");
                int salary = resultSet.getInt("salary");
                //创建员工对象:使用有参构造实例化对象
                employee=new Employee(tid,eid,ename,job,salary);
            }
            statement.close();
            connection.close();
            resultSet.close();
            //返回员工对象
            return  employee;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //查询所有
    @Override
    public List<Employee> queryALl() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
            String sql="SELECT * from t_employee";
            PreparedStatement statement = connection.prepareStatement(sql);
            ResultSet resultSet = statement.executeQuery();
            //创建返回的集合对象
            List<Employee> list=new ArrayList<>();
            //遍历结果对象
            while (resultSet.next()){
                //获取每个员工表数据的列字段信息
                Long tid = resultSet.getLong("id");
                String eid = resultSet.getString("eid");
                String ename = resultSet.getString("ename");
                String job = resultSet.getString("job");
                int salary = resultSet.getInt("salary");
                //将获取的数据封装到员工对象
                Employee employee=new Employee(tid,eid,ename,job,salary);
                //将员工对象添加到集合中
                list.add(employee);
            }
            statement.close();
            connection.close();
            resultSet.close();
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

测试类

public class EmployeeTest {
    //创建dao对象
    private IEmployeeDao employeeDao=new EmployeeDaoImpl();
    /*修改员工信息*/
    @Test
    public void employee_update(){
        employeeDao.updateEmployee(new Employee(2L,"小花","BA","tj035",9000));
    }

    /*增加员工信息*/
    @Test
    public void employee_add() {
        employeeDao.addEmployee(new Employee(null,"大黄","BA","tj036",9000));
    }

    /*根据id查询员工*/
    @Test
    public void employee_listOne() {
        Employee employee = employeeDao.queryById(1);
        System.out.println(employee);
    }

    /*查询所有*/
    @Test
    public void employee_listAll() {
        employeeDao.queryALl().forEach(System.out::println);
        List<Employee> list = employeeDao.queryALl();
        for (Employee employee : list) {
            System.out.println(employee);
        }
    }
}

文章来源:https://blog.csdn.net/zhlyxx/article/details/134922720
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。