JDBC知识点总结

JDBC

一、引言


1.1 如何操作数据

使用客户端工具访问数据库,需要手工建立链接,输入用户名和密码登录,编写SQL语句,点击执行,查看操作结果(结果集或受影响行数)。

1.2 实际开发中,会采用客户端操作数据库吗?

在实际开发过程中,当用户的数据发生改变时,不可能通过客户端操作执行SQL语句,因为操作量过大!无法保证效率和正确性

二、JDBC(Java DataBase Connectivity)


2.1 什么是JDBC?

JDBC(Java DataBase Connectivity) Java连接数据库,可以使用Java语言连接数据库完成CRUD操作

2.2 JDBC核心思想

Java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。

由数据库厂商提供驱动实现类(Driver数据库驱动)

2.2.1 MySQL数据库驱动
  • mysql-connector-java-5.1.X 适用于5.X版本
  • mysql-connector-java-8.0.X 适用于8.X版本
2.2.2 JDBC API

JDBC 是由多个接口和类进行功能实现

类型 全限定名 简介
class java.sql.DriverManager 管理多个数据库驱动类,提供了获取数据库连接的方法
interface java.sql.Connection 代表一个数据库连接(当Connection不是NULL时,表示已连接一个数据库)
interface java.sql.Statement 发送SQL语句到数据库的工具
interface java.sql.ResultSet 保存SQL查询语句的结果数据(结果集)
class java.sql.SQLException 处理数据库应用程序时所发生的异常

2.3 环境搭建

  1. 在项目下新建 lib 文件夹,用于存放 jar 文件
  2. 将MySQL驱动文件mysql-connector-java-5.1.25-bin.jar 复制到项目的lib文件夹中
  3. 选中lib文件夹 右键选择 add as library,点击OK

三、JDBC开发步骤【重点


3.1 注册驱动

使用Class.forName(“com.mysql.jdbc.Driver”); 手动加载字节码文件到JVM中

Class.forName("com.mysql.jdbc.Driver");

3.2 连接数据库

  • 通过DriverManager.getConnection(url,user,password);获得数据库连接对象
    • URL:jdbc:mysql://localhost:3306/database
    • user:root
    • password:1234
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/database?useUnicode=true&characterEncoding=utf8","root","1234");

3.3 获取发送SQL的对象

通过Connection对象获得Statement对象,用于对数据库进行通用访问的

Statement statement = connection.createStatement();

3.4 执行SQL语句

编写SQL语句,并执行,接收执行后的结果

int result = statement.executeUpdate("update stu set student_name='高强',sex='女' where student_id = 'S1003'");

3.5 处理结果

接收并处理操作结果

if(result > 0){
	System.out.println("执行成功");
}

3.6 释放资源

遵循的是先开后关的原则,释放过程中用到的所有资源对象

statement.close();
connection.close();

3.7 综合案例

综合核心六步,实现增删改

 public static void main(String[] args)throws Exception {
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.连接数据库
        String url = "jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=utf8";
        String user = "root";
        String password="1234";
        Connection connection=DriverManager.getConnection(url,user,password);

        //3.获取发送SQL的对象
        Statement statement = connection.createStatement();

        //4.编写SQL语句,执行SQL语句(返回受影响行数)
        //新增
//        String sql = "insert into stu(student_id,student_name,sex,birthday,phone,GradeId) values ('S1005','高强','女','1999-09-09','15612341234',3)";
//        String sql = "delete from stu where student_id = 'S1005'";删除
        //修改
        String sql = "update stu set student_name='高强',sex='女' where student_id = 'S1003'";
        int result = statement.executeUpdate(sql);
        //5.处理数据
        if(result > 0){
            System.out.println("执行成功!");
        }
        //6.释放资源 先开后关
        statement.close();
        connection.close();

    }

四、 ResultSet(结果集)


在执行查询SQL后,存放查询到的结果集数据

4.1 接收结果集

ResultSet rs = statement.executeQuery(sql)

ResultSet rs = statement.executeQuery("SELECT * FROM stu");

4.2 遍历ResultSet中的数据

ResultSet以表(Table)结构进行临时结果的存储,需要通过JDBC API将其中的数据进行依次获取

  • 数据行指针:初始位置在第一行数据前,每调用一次boolean next()方法,ResultSet中指针向下移动一行,结果为true,表示当前行有数据
  • rs.getXxx(“列名”); 根据列名获得数据
  • rs.getXxx(整数下标); 代表根据列的编号顺序获得!从1开始
boolean next() throws SQLException;//判断rs结果集中下一行是否有数据
4.2.1 遍历方法
int getInt(int columnIndex) throws SQLException;//获得当前行的第N列的int值
int getInt(String columnLabel) throws SQLException;//获得当前行columnLabel列的int值

4.3 综合案例

对stu表所有的数据进行遍历

4.3.1 根据列的名称获取
package com.qf.day42.t2.basic;

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

public class TestDql {
    public static void main(String[] args)  throws Exception{
        //1.注册驱动
        Class.forName("com.mysql.jdbc.Driver");

        //2.获得连接
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=utf8","root","1234");

        //3.获取执行SQL的对象
        Statement statement = connection.createStatement();

        //4.编写SQL语句
        String sql = "select student_id,student_name,sex,birthday,phone,GradeId from stu;";
        ResultSet resultSet = statement.executeQuery(sql);

        //5.处理结果 (结果集!)
        while(resultSet.next()){//判断结果集中是否有下一行!
            //根据列名获取当前行每一列的数据
            String student_id = resultSet.getString("student_id");
            String student_name = resultSet.getString("student_name");
            String sex = resultSet.getString("sex");
            String birthday = resultSet.getString("birthday");
            String phone = resultSet.getString("phone");
            int gradeId = resultSet.getInt("gradeId");
            System.out.println(student_id+"\t"+student_name+"\t"+sex+"\t"+birthday+"\t"+phone+"\t"+gradeId);
        }

        //6.释放资源
        resultSet.close();
        statement.close();
        connection.close();

    }
}

4.3.2 根据列的下标获取
 //5.处理结果 (结果集!)
        while(resultSet.next()){//判断结果集中是否有下一行!
            //根据列的编号获取当前行每一列的数据
            String student_id = resultSet.getString(1);
            String student_name = resultSet.getString(2);
            String sex = resultSet.getString(3);
            String birthday = resultSet.getString(4);
            String phone=  resultSet.getString(5);
            int gradeId  = resultSet.getInt(6);
            System.out.println(student_id+"\t"+student_name+"\t"+sex+"\t"+birthday+"\t"+phone+"\t"+gradeId);
 }

五、常见错误

  • java.lang.ClassNotFoundException 找不到类(类名书写错误、没有导入jar包)
  • com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException 与SQL语句相关的错误(表名列名书写错误、约束错误、插入的值是String类型,但是没有加单引号)建议:在客户端工具中测试sql语句后,再粘贴到代码中来
  • com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry ‘S1003’ for key ‘PRIMARY’ 原因:主键值已存在!更改要插入的主键值
  • com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException:Unknown column ‘password’ in
    • 可能输入的值的类型不对,确定插入元素时,对应的值的类型是否争取

六、综合案例【登录】


6.1 创建表

  • 创建一张用户表 User
    • id 主键、自动增长
    • username 字符串类型 非空
    • password 字符串类型 非空
    • phone 字符串类型
  • 插入2条测试语句

6.2 实现登录

  • 通过控制台,用户输入用户名和密码
  • 用户输入的用户名和密码作为参数,编写查询SQL语句。
  • 如果查询到用户,则用户存在,提示登录成功,反之,提示失败!

七、SQL注入问题


7.1 什么是SQL注入

当用户输入的数据中有SQL关键字或语法时,并且参与了SQL语句的编译,导致SQL语句编译后条件结果为true,一直得到正确的结果。称为SQL注入

7.2如何避免SQL注入

由于编写的SQL语句,是在用户输入数据后,整合后再编译成SQL语句。所以为了避免SQL注入的问题,使SQL语句在用户输入数据前,SQL语句已经完成编译,成为了完整的SQL语句,再进行填充数据

八、 PreparedStatement【重点


PreparedStatement接口继承了Statement接口。执行SQL语句的方法没有区别!

8.1 PreparedStatement的应用

作用:1.预编译SQL语句,效率高!

​ 2.安全,避免SQL注入

​ 3.可以动态的填充数据,执行多个同构的SQL语句

8.1.1 参数标记
//1.预编译SQL语句
PreparedStatement pstmt = connection.prepareStatement(sql);
8.1.2 动态参数绑定

pstmt.setXxx(下标,值); 参数下标是从1开始,为指定占位符下标绑定值

//2.为占位符下标赋值
pstmt.setString(1,username);
pstmt.setString(2,password);

九、综合练习


9.1创建数据库、表

数据库 Account

  • 创建一张表 t_ccount。有以下列
    • cardId:字符串,主键
    • password:字符串,非空
    • username:字符串,非空
    • balance:小数,非空
    • phone:字符串,非空

9.2 创建项目通过JDBC实现功能

创建AccountSystem类,完成下列功能

  • 开户:控制台输入所有的账户信息,使用PreparedStatement添加至t_account表
  • 存款:控制台输入卡号、密码、存储金额进行修改
  • 取款:输入卡号、密码、取款金额
  • 转账:输入卡号、密码、对方卡号、转账金额进行修改
  • 修改密码:控制台输入卡号、密码,再输入新密码进行修改
  • 注销:控制台输入卡号、密码,删除对应的账户信息

十、封装工具类


10.1 重用性方案

  • 封装了获取连接、释放资源两个方法
    • 提供public static Connection getConnection()方法
    • 提供public static void closeAll(Connection conn,Statement statement,ResultSet resultSet)
10.1.1 工具实现
package com.qf.day43.t1;

import sun.plugin2.gluegen.runtime.CPU;

import java.sql.*;

/**
 * 数据库工具类
 * 1、提供连接 -->Connection
 * 2、提供统一资源关闭
 * 可重用性方案
 */
public class DBUtils {


    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    //硬编码
    //获得连接
    public static Connection getConnection() {
        Connection connection = null;
        try {
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=UTF8", "root", "1234");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

    //释放资源
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

10.2 跨平台方案

  • 定义 private static final Properties properties = new Properties();//配置文件集合

  • 定义static{

    ​ //首次使用工具类,触发类加载

    ​ InputStream is = DBUtils.class.getResourceAsStream(“路径”);//复用本类自带流,读取配置文件

    ​ properties.load(is);//将is流中的配置文件信息,加载到集合中

    ​ Class.forName(properties.getProperty(“driver”));

    }

  • 在getConnection方法中。应用properties.getProperty(“url”);

10.2.1 实现

在src目录下新建db.properties文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/companydb?useUnicode=true&characterEncoding=utf8
username=root
password=123456

DBUtils代码实现

package com.qf.day43.t2;

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

/**
 * 数据库工具类
 * 1、获取连接 connection
 * 2、释放资源
 * 可跨平台方案
 */
public class DBUtils {
   private static final Properties properties = new Properties();
    static {
        try {
                //适用类自身自带的流                                        路径
                InputStream is = DBUtils.class.getResourceAsStream("/db.properties");

                properties.load(is);//通过流,将配置信息的内容分割成键值对

                Class.forName(properties.getProperty("driver"));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        Connection connection = null;
        try {
            connection = DriverManager.getConnection(properties.getProperty("url"),properties.getProperty("username"),properties.getProperty("password"));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }


    //释放资源
    public static void closeAll(Connection connection, Statement statement, ResultSet resultSet) {
        try {
            if (resultSet != null) {
                resultSet.close();
            }
            if (statement != null) {
                statement.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

十一、ORM


ORM(Object Relational Mapping)

从数据库查询到的结果集(ResultSet)在进行遍历时,逐行遍历,取出的都是零散的数据。在实际应用开发中,我们需要将零散的数据进行封装整理

11.1 ORM 实体类(entity):零散数据的载体

11.1.1 ORM应用
package com.qf.day43.t2;

public class User {
    private int id;
    private String username;
    private String password;
    private String sex;
    private String email;
    private String address;
    public User(){}

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", sex='" + sex + '\'' +
                ", email='" + email + '\'' +
                ", address='" + address + '\'' +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public User(int id, String username, String password, String sex, String email, String address) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.sex = sex;
        this.email = email;
        this.address = address;
    }
}

package com.qf.day43.t2;

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

public class OrmSelect {
    public static void main(String[] args) {
        Connection connection = DBUtils.getConnection();
        String sql = "select id,username,PASSWORD,sex,email,address from `user`;";
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            preparedStatement = connection.prepareStatement(sql);
            System.out.println(preparedStatement);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {//拿到每一行数据、
                //拿到每一列的数据
                User user = new User();
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String password = resultSet.getString("password");
                String sex = resultSet.getString("sex");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                //将一行中零散的数据,封装在一个User对象里。
                user.setId(id);
                user.setUsername(username);
                user.setPassword(password);
                user.setSex(sex);
                user.setEmail(email);
                user.setAddress(address);
                System.out.println(user);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, resultSet);
        }
    }
}

十二、DAO(Data Access Object)


数据访问对象

**
 * 对数据库中User表的一系列操作。
 * 只做对数据库访问的操作!\
 * 复用! 对同一张表的操作 实现复用
 */
public class UserDaoImpl {
    private Connection connection = null;
    private PreparedStatement preparedStatement = null;
    private ResultSet resultSet = null;

    //增
    public int insert(User user) {
        try {
            connection = DBUtils.getConnection();
            String sql = "insert into user(id,username,password,sex,email,address) values(?,?,?,?,?,?);";
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, user.getId());
            preparedStatement.setString(2, user.getUsername());
            preparedStatement.setString(3, user.getPassword());
            preparedStatement.setString(4, user.getSex());
            preparedStatement.setString(5, user.getEmail());
            preparedStatement.setString(6, user.getAddress());

            int i = preparedStatement.executeUpdate();
            return i;//将操作结果返回给调用者!
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, null);
        }
        return 0;
    }

    //删
    public int delete(int id) {
        connection = DBUtils.getConnection();
        String sql = "delete from user where id = ?";

        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, id);
            return preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, resultSet);
        }
        return 0;
    }

    //改
    public int update(User user) {
        connection = DBUtils.getConnection();
        String sql = "update user set username=?,password=?,sex=?,email =?,address=? where id = ?";
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, user.getUsername());
            preparedStatement.setString(2, user.getPassword());
            preparedStatement.setString(3, user.getSex());
            preparedStatement.setString(4, user.getEmail());
            preparedStatement.setString(5, user.getAddress());
            preparedStatement.setInt(6, user.getId());
            return preparedStatement.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, resultSet);
        }
        return 0;
    }

    //查单个
    public User select(int id) {
        connection = DBUtils.getConnection();
        String sql = "select id,username,password,sex,email,address from user where id = ?;";
        try {
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, id);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                int id1 = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String password = resultSet.getString("password");
                String sex = resultSet.getString("sex");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                User user = new User(id1, username, password, sex, email, address);
                return user;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, resultSet);
        }
        return null;
    }

    //查多个
    public List<User> selectAll() {
        connection = DBUtils.getConnection();
        String sql = "select id,username,password,sex,email,address from user";
        List<User> userList = new ArrayList<>();
        try {
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String password = resultSet.getString("password");
                String sex = resultSet.getString("sex");
                String email = resultSet.getString("email");
                String address = resultSet.getString("address");
                User user = new User(id, username, password, sex, email, address);

                userList.add(user);//每封装完一个对象,添加到集合当中
            }
            return userList;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtils.closeAll(connection, preparedStatement, resultSet);
        }
        return null;
    }
}

十三、日期类型


  • java.util.Date
    • Java语言常规应用层面的日期类型。可以通过字符串创建对应的时间对象
    • 无法直接通过JDBC插入数据库
  • java.sql.Date
    • 不可以通过字符串创建对应的时间对象。只能通过毫秒值创建对象(1970年1月1日至今的毫秒值)
    • 可以直接通过JDBC插入数据库

13.1 日期格式化工具

SimpleDateFormat 日期格式化

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//按照指定格式转换成util.Date类型
java.util.Date date = sdf.parse("2000-01-01");

13.2 日期工具类 DateUtil

package com.qf.day43.t4;

import java.text.ParseException;
import java.text.SimpleDateFormat;

/**
 * 日期转换
 * 字符串转UtilDate
 * 字符串转SqlDate
 * utilDate转成Sqldate
 */
public class DateUtils {
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    //字符串转Util
    public static java.util.Date strToUtilDate(String str) {
        try {
            return simpleDateFormat.parse(str);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
    //字符串转sql
//    public static java.sql.Date strToSqlDate(String str){
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//        try {
//            java.util.Date date = simpleDateFormat.parse(str);
//            return new java.sql.Date(date.getTime());
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
//        return null;
//    }

    //util转sql
    public static java.sql.Date utilToSql(java.util.Date date){
        return new java.sql.Date(date.getTime());
    }

}

13.2.1 测试
package com.qf.day43.t4;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class TestDatetimes {
    public static void main(String[] args) throws ParseException {
        //1.java.util.Date 当前系统时间
//        System.out.println(new java.util.Date());
//
//        //自定义一个时间
//        String str = "1999-09-09";
//        //日期转换   字符串转为 java.util.Date
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        
//        //将日期字符串转换成 util.Date类型
//        java.util.Date utilDate  = sdf.parse(str);
//        System.out.println(utilDate);
//
//        //sql.Date  需要毫秒值,来构建一个日期
//        java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
//        System.out.println(sqlDate);
//
//
//        java.util.Date date = DateUtils.strToUtilDate("2002-3-18");
//        System.out.println(date);
//
//        java.sql.Date date2 = DateUtils.utilToSql(date);
//        System.out.println(date2);

        System.out.println(new java.util.Date());

        System.out.println(new java.sql.Date(new java.util.Date().getTime()));
    }
}

发布了40 篇原创文章 · 获赞 0 · 访问量 1122

猜你喜欢

转载自blog.csdn.net/qq_41841482/article/details/105204151
今日推荐