JavaLearn#(18)JDBC基本操作(CRUD)使用PreparedStatementJDBC事务员工管理系统Properties类log4j框架数据库连接池

Posted LRcoding

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaLearn#(18)JDBC基本操作(CRUD)使用PreparedStatementJDBC事务员工管理系统Properties类log4j框架数据库连接池相关的知识,希望对你有一定的参考价值。

1. JDBC 基本操作

1.1 JDBC 概述

  • 是一种用于执行 SQL 语句的 Java API,为多种关系型数据库提供统一访问

  • SUN公司制定了规范JDBC
    • DriverManager 类:管理各种不同的 JDBC 驱动
    • Connection 接口:连接数据库用
    • Statement 接口和 PreparedStatement 接口:发送SQL请求
    • ResultSet 接口:接收返回值

JDBC访问数据库的步骤

  • 加载一个 Driver 驱动
  • 创建数据库连接 (Connection)
  • 创建 SQL 命令发送器 Statement
  • 通过 Statement 发送 SQL 命令并得到结果 ResultSet
  • 处理结果(select语句返回的结果)
  • 关闭数据库资源(ResultSet、Statement、Connection)

1.2 添加、修改、删除操作

url 的一般后缀:useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

public static void main(String[] args) 
    Connection conn = null;
    Statement stmt = null;
    try 
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/adb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        String user = "root";
        String passwd = "root";

        // 1.加载驱动(添加 jar 包)
        Class.forName(driver);

        // 2.建立连接
        conn = DriverManager.getConnection(url, user, passwd);

        // 3.创建SQL命令的发送器
        stmt = conn.createStatement();

        // 4.准备一个SQL命令,并使用SQL发送器发送,并返回结果
        String sql = "INSERT INTO dept VALUES(50, '教学部', '北京')";                    // 插入操作
        String sql = "UPDATE dept SET dname = '试验部' WHERE deptno = 50";               // 更新操作
        String sql = "DELETE FROM dept WHERE deptno = 50";                              // 删除操作
        int res = stmt.executeUpdate(sql);    // INSERT、UPDATE、DELETE 操作

        // 5.处理结果
        if (res > 0) 
            System.out.println("添加成功");
         else 
            System.out.println("添加失败");
        
     catch (SQLException e) 
        e.printStackTrace();
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     finally 
        // 6.关闭资源
        try 
            if (stmt != null) 
                stmt.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
        try 
            if (conn != null) 
                conn.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
    

1.3 查询操作

ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。

初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后指向最后一条记录的后面

public static void main(String[] args) 
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    try 
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/adb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        String user = "root";
        String passwd = "root";

        // 1.加载驱动(添加 jar 包)
        Class.forName(driver);

        // 2.建立连接
        conn = DriverManager.getConnection(url, user, passwd);

        // 3.创建SQL命令的发送器
        stmt = conn.createStatement();

        // 4.准备一个SQL命令,并使用SQL发送器发送,并返回结果
        String sql = "SELECT * FROM emp";
        rs = stmt.executeQuery(sql);                    // 【 executeQuery 操作】!!!!!!!!!!!!

        // 5.处理结果
        System.out.println("编号\\t姓名\\t入职时间\\t薪水");
        while (rs.next()) 
            // 获取当前行各列的数据
            int empno = rs.getInt("empno");            // 通过名字获取值!!!!
            String ename = rs.getString("ename");
            Date hireDate = rs.getDate("hireDate");
            double sal = rs.getDouble("sal");

            // 输出数据【或者可以将数据通过 构造方法 放到实体类中,最后返回实体类的集合List】
            System.out.println(empno + "\\t" + ename + "\\t" + hireDate + "\\t" + sal);
        
     catch (SQLException e) 
        e.printStackTrace();
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     finally 
        // 6.关闭资源
        try 
            if (rs != null) 
                rs.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
        try 
            if (stmt != null) 
                stmt.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
        try 
            if (conn != null) 
                conn.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
    

可以定义实体类进行结果的封装

2. JDBC 高级操作

2.1 使用PreparedStatement

案例:模拟淘宝登录功能。在前台输入用户名和密码,后台进行验证,验证结果反馈给前台

-- 创建用户表 t_user
CREATE TABLE t_user(
    user_id  VARCHAR(10) PRIMARY KEY , --字符串做主键无法实现自增
    real_name VARCHAR(3) NOT NULL,
    passwd VARCHAR(6) NOT NULL,
    money  DOUBLE(10,2)
 );
-- 插入用户
 INSERT INTO t_user VALUES('zhangsan','张三','zhangs',5000);
 INSERT INTO t_user VALUES('lisi','李四','******',5000);

Java代码:

public class LoginDemo 
    /** 模拟前台 */
    public static void main(String[] args) 
        Scanner in = new Scanner(System.in);
        System.out.print("输入用户名:");
        String userId = in.next();
        System.out.print("输入密码:");
        String pwd = in.next();

        // 调用后台判断登录是否成功,并返回结果
        User user = login(userId, pwd);

        // 在前台输出结果
        if (user != null) 
            System.out.println("欢迎您:" + user.getRealName());
         else 
            System.out.println("登录失败");
        
    

    public static User login(String userId, String pwd) 
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        User loginUser = null;
        try 
            String driver = "com.mysql.cj.jdbc.Driver";
            String url = "jdbc:mysql://127.0.0.1:3306/adb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
            String user = "root";
            String passwd = "root";

            Class.forName(driver);
            conn = DriverManager.getConnection(url, user, passwd);
            stmt = conn.createStatement();

            // 使用 Statement 需要拼接 SQL语句 !!!!!!!
            String sql = "SELECT * FROM t_user WHERE user_id = '" + userId
                    + "' AND passwd = '" + pwd + "'";
            rs = stmt.executeQuery(sql);

            if (rs.next()) 
                String realName = rs.getString("real_name");
                double money = rs.getDouble("money");
                loginUser = new User(userId, realName, pwd, money);
                // String userId = rs.getString("user_id");   不需要获取,用户输入的
                // String passwd = rs.getString("passwd");
            
         catch (SQLException e) 
            e.printStackTrace();
         catch (ClassNotFoundException e) 
            e.printStackTrace();
         finally 
            if (rs != null) 
                try 
                    rs.close();
                 catch (SQLException throwables) 
                    throwables.printStackTrace();
                
            
            if (stmt != null) 
                try 
                    stmt.close();
                 catch (SQLException throwables) 
                    throwables.printStackTrace();
                
            
            if (conn != null) 
                try 
                    conn.close();
                 catch (SQLException throwables) 
                    throwables.printStackTrace();
                
            
        
        return loginUser;
    


class User 
    private String userId;
    private String realName;
    private String passwd;
    private Double money;

    public User() 
    

    public User(String userId, String realName, String passwd, Double money) 
        this.userId = userId;
        this.realName = realName;
        this.passwd = passwd;
        this.money = money;
    
    // getter   setter   toString方法

此时随便输入用户名,密码后边跟 'or'1'='1,也可以登录,没有安全性

=====》 使用 PreparedStatment 进行操作

PreparedStatement pstmt = null;

String sql = "SELECT * FROM t_user WHERE user_id = ? AND passwd = ?";  // ? 为占位符
pstmt = conn.prepareStatement(sql);
// 将占位符换为真正的参数
pstmt.setString(1, userId);
pstmt.setString(2, pwd);

rs = pstmt.executeQuery();
  • PreparedStatment 继承自 Statement
  • PreparedStatment 不是字符串的拼接,需要传入参数
  • PreparedStatment 安全性高,可以避免SQL 注入,性能高 (同一个sql语句,只第一次处理的时候费时,后续速度变快)

2.2 使用事务

  • 在JDBC中,事务操作缺省都是自动提交的
    • 一条对数据库的DML(INSERT、UPDATE、DELETE)代表一项事务操作
    • 操作成功自动调用 commit() 提交,失败自动调用 rollback()
public static void main(String[] args) 
    Connection conn = null;
    Statement stmt = null;
    try 
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://127.0.0.1:3306/adb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
        String user = "root";
        String passwd = "root";

        Class.forName(driver);
        conn = DriverManager.getConnection(url, user, passwd);
        stmt = conn.createStatement();

        // 设置事务不再自动提交
        conn.setAutoCommit(false);

        stmt.executeUpdate("UPDATE t_user SET money = money - 2000 WHERE user_id = 'lisi'");
        stmt.executeUpdate("UPDATE t_user SET money = money + 2000 WHERE user_id = 'zhangsan'");

        // 事务成功结束
        conn.commit();
     catch (SQLException e) 
        try 
            // 事务异常结束,则回滚
            conn.rollback();
         catch (SQLException throwables) 
            throwables.printStackTrace();
        
        e.printStackTrace();
     catch (ClassNotFoundException e) 
        e.printStackTrace();
     finally 
        try 
            if (stmt != null) 
                stmt.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
        try 
            if (conn != null) 
                conn.close();
            
         catch (SQLException e) 
            e.printStackTrace();
        
    

3. JDBC总结

Connection接口

  • 作用:代表数据库连接

DriverManager类

  • 作用:管理一组 JDBC 驱动程序的基本服务
  • 应用程序不再需要使用 Class.forName() 显式地加载 JDBC 驱动程序。在调用 getConnection 方法时,DriverManager 会试着从初始化时加载的那些驱动程序以及使用与当前 applet 或应用程序相同的类加载器显式加载的那些驱动程序中查找合适的驱动程序。

Statement接口

  • 作用:用于将 SQL 语句发送到数据库中,或理解为执行sql语句
  • 有三种 Statement对象:
    • Statement:用于执行不带参数的简单SQL语句;
    • PreparedStatement(从 Statement 继承):用于执行带或不带参数的预编译SQL语句;
    • CallableStatement(从PreparedStatement 继承):用于执行数据库存储过程的调用。
方法作用
ResultSet executeQuery(String sql)执行SQL查询并获取到ResultSet对象
boolean execute(String sql)可以执行任意SQL语句,然后获得一个布尔值,表示是否返回ResultSet
int executeUpdate(String sql)可以执行插入、删除、更新等操作,返回值是执行该操作所影响的行数

PreparedStatement接口

  • 关系:public interface PreparedStatement extends Statement
  • 区别
    • PreparedStatment安全性高,可以避免SQL注入
    • PreparedStatment简单不繁琐,不用进行字符串拼接
    • PreparedStatment性能高,用在执行多个相同数据库DML操作时

ResultSet接口

  • ResultSet对象是executeQuery()方法的返回值,它被称为结果集,它代表符合SQL语句条件的所有行,并且它通过一套getXXX方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问
  • ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环
  • ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行
  • 初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后指向最后一条记录的后面。

方法名说 明
boolean next()将光标从当前位置向下移动一行
boolean previous()游标从当前位置向上移动一行
void close()关闭ResultSet 对象
int getInt(int colIndex)以int形式获取结果集当前行指定列号值
int getInt(String colLabel)以int形式获取结果集当前行指定列名值
float getFloat(int colIndex)以float形式获取结果集当前行指定列号值
Float getFloat(String colLabel)以float形式获取结果集当前行指定列名值
String getString(int colIndex)以String 形式获取结果集当前行指定列号值
StringgetString(String colLabel)以String形式获取结果集当前行指定列名值

4. 员工管理系统

功能:查询所有 按照编号查询 添加员工 更新员工 删除员工

4.1 搭建项目框架

  • 创建项目 empmgr
  • 添加jar包
  • 创建包
    • com.bjsxt.dao 后台:存放访问数据库的接口 EmployeeDao
    • com.bjsxt.dao.impl 后台: 存放访问数据库的实现类 EmployeeDaoImpl
    • com.bjsxt.entity 后台:存放实体类 Employee
    • com.bjsxt.test 前台
    • com.bjsxt.util 工具类,提取数据库常用操作便于重复调用,避免代码重复
  • 创建实体类Employee
  • 创建后台的接口EmployeeDao和实现类EmployeeDaoImpl
    • public List<Employee> findAll();
    • public Employee findById(int empno);
    • public int save(Employee emp);
    • public int update(Employee emp);
    • public void delete(int empno);

4.2 查询所有员工

后台方法

public List<Employee> findAll() 
    String driver = "com.mysql.cj.jdbc.Driver";
    String url = "jdbc:mysql://127.0.0.1:3306/adb?useSSL=false&useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai";
    String user = "root";
    String password = "root";
    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;
    List<Employee> employeeList = new ArrayList<>();
    try 
        Class.forName(driver);
        conn = DriverManager.getConnection(url, user, password);
        stmt = conn.createStatement();
        String sql = "SELECT * FROM emp";
        rs = stmt.executeQuery(sql);
        while (rs.next()) 
            Employee emp = new Employee以上是关于JavaLearn#(18)JDBC基本操作(CRUD)使用PreparedStatementJDBC事务员工管理系统Properties类log4j框架数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章

JavaLearn # Java的常用类

JavaLearn#(21)JavaScript入门基本语法函数基本对象数组事件DOM和BOM

JavaLearn#(21)JavaScript入门基本语法函数基本对象数组事件DOM和BOM

JDBC 基本语法总结

JavaLearn#(22)jQuery介绍选择器事件动画DOM编程操作CSS表单验证

JavaLearn#(22)jQuery介绍选择器事件动画DOM编程操作CSS表单验证