JDBC - 学习1 - 简单使用

10 篇文章 0 订阅

JDBC - java.sql包

1. 概念

JDBC( Java DataBast Connectivity ): Java数据库连接

默认:执行DML操作、关闭连接 自动Commit 更新的数据

数据持久化: 数据保存到可掉电式存储设备,例如:将内存数据存到硬盘、磁盘文件、xml数据文件、数据库等等

不同的数据库方法接口
统一数据库方法的接口
DBMS - 各种不同厂商的数据库
JDBC
java应用程序
JDBC结构组成
JDBC API - 方法接口
JDBC Driver Interface - 驱动接口

     数据库驱动的分类

数据库驱动: 各数据库厂商实现的JDBC接口的实现类

数据库驱动程序分类
jdbc-odbc桥 -- ( jdbc调用 → odbc调用 )
本地API驱动 - ( jdbc调用 → 数据库标准调用 )
网络协议驱动 - ( 数据库请求 发送给 中间服务器 )
本地协议驱动 - ( jdbc调用 → 数据库系统规范请求、效率最高 )


     四种数据库驱动步骤

桥驱动
本地API
网络协议
本地协议
JDBC接口
JDBC驱动管理
jdbc-odbc桥驱动
odbc API
数据库客户端库
部分java-jdbc驱动程序
纯java-jdbc驱动程序
数据库中间服务器
数据库服务器

2. JDBC核心类、接口

重点: 我们需要需要面向JDBC接口编程,尽可能少的出现第三方驱动的代码 – 使代码具有可移值性

接口编程
利用反射进行加载JDBC驱动
利用配置文件进行加载驱动
前两者都不能用,则利用全限定名进行加载驱动
尽可能的少 import 驱动jar包 - 因为已经把代码写死了
JDBC核心类
类Class
DriverManager - 负责管理JDBC驱动程序
SQLException - 数据库操作异常
接口Interface
Connection - 与数据库连接(会话session)
PreparedStatement - 已编译的sql语句、可多次使用
Statement - 静态sql语句
ResultSet - sql查询的结果集
CallableStatement - 存储过程语句

3. 使用JDBC
Statement对象执行SQL语句分类
execute( sql语句 )
true:查询有结果集
false:更新结果集 或者 查询无结果集
executeQuery( sql语句 )
返回:sql查询语句得到的结果集
executeUpdate( sql语句 )
返回:DML语句对表影响的行数
executeBatch()
返回:int[] 执行多条DML语句,数组整数表示DML分别所影响的行数



     连接数据库的步骤

1. JDBC驱动程序的载入
2. 定义连接URL
3. 建立连接(会话)
4. 创建并初始化Statement对象
5. 执行查询、更新
6. 得到结果、并处理使用
7. 关闭连接(会话)


3.1 Statement

Connection对象.createStatement() → 返回Statement对象

statement弊端
1. 拼接字符串,且不能忽略原SQL表示字符串的' ' 单引号
2. 注入攻击 -- 拼接字符串所有能改变where的查询结果
3. 传不了图片、视频、音频等关于BLOB文件流的文件到数据库

public static void main( String[] args ) {
     Connection con;
     Statement state;
     ResultSet rs;
     try {
         // 1. 加载JDBC-Oracle驱动
        Class.forName( "oracle.jdbc.driver.OracleDriver")  

        // 2. 定义初始并初始话连接字符串、登录的数据库用户名、该用户名下的用户密码
        String url = "jdbc:oracle:thin:@localhost:1521:orcl";  
        String userName = "scott";               
        String userPassword = "123456"              

        // 3. 连接数据库
       conn = DriverManager.getConnection( url, userName, userPassword );

        // 4. 创建 将SQL语句送到数据库的对象
       state = conn.createStatement();

        // 5. 执行SQL语句、并得到结果查询结果集
        rs = state.executeQuery( "select * from emp" );

        // 6. 处理打印结果集在控制台中
        while( rs.next() ) {
            Integer empno = rs.getInt("empno");
            Date hiredate = rs.getDate("hiredate");     
            System.out.println( "empno: " + empno + "    hiredate: " + hiredate );   
        }    
    }catch(Exception e) {
        e.printStackTrace();
    }finally// 7. 关闭连接:顺序 结果集 → SQL语句声明 → 连接对象
        try {
            rs.close();
            state.close();
            conn.close();
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
}


  Statement注入风险


// 这条函数的用意是传一个 数字进去,根据empno值查询数据
public static List<Emp>  queryEmp( String empno ) throws Exception {
    Connection conn;
    Statement state;
    ResultSet rs;
    ArrayList<Emp> empList = new ArrayList<Emp>();
    Class.forName("oracle.jdbc.driver.OracleDriver");
    
    conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:orcl", "scott", "123456");
    state = conn.createStatement();
    
    rs = state.executeQuery( "select * from emp where empno = " + empno );
    while (rs.next()) {
                     Emp emp = new Emp();
                     emp.setEmpno(rs.getInt("empno"));
                     emp.setEname(rs.getString("ename"));
                     emp.setJob(rs.getString("job"));
                     empList.add(emp);
    }    
    return empList;
}


//调用
queryEmp("1234 or 1=1")  →   注入查询,导致全部数据输出出来


3.2 PreparedStatement

Connection对象.prepareStatement( sql语句 ) → 返回PreparedStatement对象

在写sql语句的时候遇到表名、列名是关键字的时候,需要用 ``(英文符号,键盘1左边的斜点)来进行包裹

PreparedStatement优势
1. 无需字符串拼接、无SQL注入问题
2. 能操纵BLOB数据
3. 批量操作非常好 - sql语句只编译一次,可重复使用

  PreparedStatement预编译语句的好处

  • SQL语句的大体结构已经保存,到时只要修改筛选的条件即可
  • 防止SQL注入风险 → 因为我们把整个SQL语句已经写死,无需拼接,用户只需要传查询条件进来即可以
//简略的输写,异常检测这些忽略不写
Connection conn =  DriverManager.getConnection( url, userName, userPassword );

// 这条SQL语句已经编译好了,到时只要更改问号的值即可以查询不同的数据集
// ?问号表示占位号,在执行前,必须赋值给问号
PreparedStatement state = conn.prepareStatement("select * from emp where empno = ?");

// state.set列类型( 第几个问号, 列值 );  //从1开始

state.setInt(1, 8981);    
state.executeQuery();   //  有一条结果集

state.setInt(1, 7369);    
state.executeQuery();   // 有一条结果集


3.3 CallableStatement

Connection对象.prepareCall( sql语句 ) → 返回CallableStatement对象

4. 获取数据库的连接字段、以及连接数据类似DBMS操纵数据库
  1. 使用Eclipse自带的Data Management工具进行获取与对应的数据库连接的连接字符串,打开方式: 窗口 → 显示视图 → Data Management → Data Source Explorer

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f8IvMihA-1574124983838)(en-resource://database/4965:1)]

  1. 打开后 Data Source Explorer界面如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ha8M6jSJ-1574124983851)(en-resource://database/4967:1)]

  1. Database Connections右键 → New → 选择需要连接的数据库 → 下一步

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ggqihFEn-1574124983865)(en-resource://database/4969:1)]

  1. 点击 New Driver Definition

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nWEKy7DK-1574124983868)(en-resource://database/4971:1)]

  1. Name/Type下 → 选择加载的JDBC驱动版本、JAR List下 → 导入JDBC驱动文件、Propertties下 → 设置连接字符串、密码、账户等登录信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vdf2hvox-1574124983876)(en-resource://database/4973:1)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YS25uftU-1574124983879)(en-resource://database/4975:1)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sNcCDKNt-1574124983884)(en-resource://database/4981:1)]

  1. 确定 → Test Connection → 如有下图则进行下一步、不成功则自己重新检查前面的设置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZebS6mgF-1574124983890)(en-resource://database/4983:1)]

  2. 下一步( 能看到所有设置信息 ) → 完成 → 即可以类似DBMS一样使用,不过功能比较少
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZrR5KHU4-1574124983896)(en-resource://database/4985:1)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uXP0Wqvn-1574124983901)(en-resource://database/4987:1)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值