Day43-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.3 JDBC API

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

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

2.4 环境搭建

  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");
  • URL(Uniform Resource Locator)统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成

3.3 获取发送SQL的对象

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

Statement statement = connection.createStatement();

3.4 执行SQL语句

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

int result = statement.executeUpdate("update stu set  where ");
  • 注意:在编写DML语句时,一定要注意字符串参数的符号是单引号 ‘值’
  • DML语句:增、删、改时,执行的结果是受影响行数(int类型)。
  • DQL语句:查询时,返回的是数据结果集(ResultSet结果集)

3.5 处理结果

接收并处理操作结果

if(result > 0){
	System.out.println("执行成功");
}
  • 受影响行数:逻辑判断,方法返回
  • 查询结果集:迭代、依次获取

3.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值

注意:列的编号从1开始

4.3 综合案例

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


4.3.1 根据列的名称获取
public class Test {
    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","root");

        //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
    • 可能输入的值的类型不对,确定插入元素时,对应的值的类型是否争取

六、SQL注入问题

6.1 什么是SQL注入

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


6.2如何避免SQL注入

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


七、 PreparedStatement

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

7.1 PreparedStatement的应用

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

			2.安全,避免SQL注入

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

7.1.1 参数标记

//1.预编译SQL语句
PreparedStatement pstmt = connection.prepareStatement(sql);

注意:PreparedStatement应用时,SQL字符串的参数都由?符号站位,被称为参数标记。在执行该SQL语句前,要为每个?参数赋值


7.1.2 动态参数绑定

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

//2.为占位符下标赋值
pstmt.setString(1,username);
pstmt.setString(2,password);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值