Oracle独特的技术、JDBC

文章目录

  • 一. Oracle独特的技术
    • 1. 过气技术
    • 2. 虚表 dual
    • 3. 序列 sequence
    • 4. 授权视图
    • 5. 视图 view
    • 6. 触发器 trigger
    • 7. 存储过程 procedure
  • 二. JDBC
    • 1. 概念
    • 2. 使用
    • 3. 向IDEA中导入jar包
    • 4. 入门案例
    • 5. SQL攻击注入的解决方案

一. Oracle独特的技术

1. 过气技术

下面技术在历史长河中已经被淘汰但老项目,小项目依然在用,只做了解.

2. 虚表 dual

dual是一个虚拟表,MySQL没有,用来构成select的语法规则,Oracle保证dual里永远只有一条记录,用它可以做很多事.

将结果存储在dual表中:

select 1 from dual;					虚拟出一个数字列
select 'abc' from dual;				虚拟出一个字符串列
select sysdate from dual;		获取系统当前日期
select sys_guid() from dual;	获取uuid

3. 序列 sequence

Oracle自身提供的自增主键支持,和MySQL的实现思路完全不同.
Oracle独特的技术、JDBC_第1张图片
Oracle独特的技术、JDBC_第2张图片

4. 授权视图

使用system登录,修改ht的权限为dba,否则无法创建视图.
Oracle独特的技术、JDBC_第3张图片
Oracle独特的技术、JDBC_第4张图片
或者

使用system账户执行,分配视图权限.

grant create any view to ht;

5. 视图 view

视图本质就是一个查询,和我们自己查询的区别是,它执行完会有缓存,下次查询就直接使用.但其它因为实现缓存,无法做优化,大型项目中禁止使用.
Oracle独特的技术、JDBC_第5张图片注意: 视图只需创建一次,后面就可以类似表来使用,只是用来查询不能更新和删除.

创建视图 ,本质上就是缓存一个查询结果
create or replace view STU_V as
  select * from  stu where ssex=0
查询表结构
select * from  stu where ssex=0
直接查询视图,高效,但是无法优化
select * from  STU_V
可以看到两者查询结果没有分别

6. 触发器 trigger

记录生效点:BEFORE/AFTER

记录的操作:INSERT/UPDATE/DELETE
Oracle独特的技术、JDBC_第6张图片
Oracle独特的技术、JDBC_第7张图片
需求:当修改sex值时触发逻辑.

--设置触发器 ---禁用,因为无法控制程序员的权限,可能有安全隐患
create or replace trigger UPDATE_STU_TRI
  before update on stu 
  for each row
declare
  -- local variables here
begin
  --如果 SEX>0,统一设置成1
  IF :NEW.SSEX>5 THEN 
       :NEW.SSEX := 1;
  END IF;
end UPDATE_STU_TRI;

--使用触发器:
SELECT * FROM STU
update stu set ssex=10;--触发器执行,都是1了
update stu set ssex=3;--不满足触发器,就是3

7. 存储过程 procedure

概念:

存储过程(Stored Procedure)其实就是数据库端的编程,在数据库为王的时代,虽然已经过去,当时数据库大集中,部署在超级好的服务器,甚至是小型机,所以执行的性能超群,运行在上面的程序自然也就性能极佳。但当分布式架构兴起后,数据库在整个架构中的作用一再衰落,逐步边缘化。再者存储过程中的SQL是依赖数据库厂商,每个厂商都有其个性的SQL,导致程序迁移数据库时,如从oracle迁移到mysql时基本重写,工作量巨大,造成修改的风险。于是主流方式已经将其从数据库端前置到java程序端实现,这样迁移数据库变得轻松。

二. JDBC

1. 概念

我们学习了数据库,数据库实现了数据的持久化,但我们最终要在程序里处理数据,那java代码中怎么去访问数据库读写数据呢?

这就要用到sun公司设定的一套数据库标准了,这套标准就是JDBC(Java Database Connectivity)。但它只是规范,不做具体实现。于是数据库厂商又根据JDBC标准,实现自家的驱动Driver。如:MySQL驱动com.mysql.cj.jdbc.Driver,Oracle的驱动oracle.jdbc.OracleDriver。有了这套解决方案,java就可以访问数据库中的数据了。

public interface Connection  extends Wrapper, AutoCloseable {}

public interface Statement extends Wrapper, AutoCloseable {}

public interface PreparedStatement extends Statement {}

public interface CallableStatement extends PreparedStatement {}

public interface ResultSet extends Wrapper, AutoCloseable {}

Java中提倡面向接口开发,而最经典的接口设计莫过于JDBC数据库接口。

Connection链接、Statement语句、PreparedStatement预处理语句、CallableStatement存储过程、ResultSet结果集。

调用方式有三种:Statement语句、PreparedStatement预处理语句、CallableStatement存储过程,推荐使用第二种PreparedStatement,防止SQL注入,其也是预编译性能高。

2. 使用

2.1 导入jar包(丰富的工具类)

2.2 获取和数据库的连接(用户名、密码)

2.3 通过程序执行SQL

2.4 通过程序处理结果

3. 向IDEA中导入jar包

3.1 创建Java工程

3.2 创建lib目录,拷贝驱动 objbc6-11.1.0.7.0 到 lib 目录下

3.2 项目引用这个外部jar包
Oracle独特的技术、JDBC_第8张图片
Oracle独特的技术、JDBC_第9张图片
Oracle独特的技术、JDBC_第10张图片

4. 入门案例

import java.sql.*;

public class Test1 {
    public static void main(String[] args) throws Exception {
        // 1. 注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        // 2. 获取和数据库的连接
        // String url = "jdbc:mysql://localhost:3306/py_school_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
        String url = "jdbc:mysql:///py_school_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
        String user = "root";
        String password = "root";
        Connection conn = DriverManager.getConnection(url, user, password);
        // 3. 获取传输器
        Statement st = conn.createStatement();
        // 4. 执行SQL
        ResultSet rs = st.executeQuery("select * from students");
        // 5. 解析结果
        while (rs.next()){
            // 获取数据
            for (int i = 1 ; i <= 5 ; i++){
                System.out.println(resultSet.getString(i));
            }
        }
        // 6. 释放资源
        rs.close();
        st.close();
        conn.close();
    }
}

5. SQL攻击注入的解决方案

5.1 不安全:

private static void login() throws Exception {
    Class.forName("com.mysql.cj.jdbc.Driver");
    String url = "jdbc:mysql:///lz?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
    String user = "root";
    String password = "root";
    Connection connection = DriverManager.getConnection(url, user, password);
    /**
     * 传输器在执行SQL时不安全
     */
    Statement statement = connection.createStatement();

    System.out.println("请输入用户名: ");
    String name = new Scanner(System.in).nextLine();
    System.out.println("请输入密码: ");
    String pass = new Scanner(System.in).nextLine();
    // SQL注入攻击问题: 本质上是因为SQL语句中出现了特殊符号#,改变了SQL语义
    String sql = "select * from user where name='" + name + "' and password='" + pass + "'";
    ResultSet resultSet = statement.executeQuery(sql);
    if (resultSet.next()){
        System.out.println("登陆成功!");
    }else {
        System.out.println("查无此人!");
    }
    resultSet.close();
    statement.close();
    connection.close();
}

5.2 解决办法

/*总结:
	作用: java程序和数据库连接的技术
		    SQL注入攻击问题:拼接SQL时,出现了特殊符号#,只需要输入用户名而不需要密码都可以登录
		    SQL注入攻击解决方案:不用Statement,换成了PreparedStatement,
		            新的工具类的好处:不用自己拼SQl的字符串了,安全,高效
		    PreparedStatement的解决过程:先把SQL骨架发给数据库,数据库进行预编译
		            等到设置好了参数,再和骨架一起执行,避免了人为的恶意的拼串造成的隐患
		 */
private static void login2() throws Exception {
    Class.forName("com.mysql.cj.jdbc.Driver");
    String url = "jdbc:mysql:///lz?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false";
    String user = "root";
    String password = "root";
    Connection connection = DriverManager.getConnection(url, user, password);
    System.out.println("请输入用户名: ");
    String name = new Scanner(System.in).nextLine();
    System.out.println("请输入密码: ");
    String pass = new Scanner(System.in).nextLine();
    /**
     * ?: 占位符
     * SQL骨架
     */
    String sql = "select * from user where name=? and password=?";
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    // 给SQL设置参数
    /**
     * preparedStatement.setString(参数索引,参数值);
     */
    preparedStatement.setString(1,name);
    preparedStatement.setString(2,pass);
    ResultSet resultSet = preparedStatement.executeQuery();
    if (resultSet.next()){
        System.out.println("登陆成功!");
    }else {
        System.out.println("查无此人!");
    }
    resultSet.close();
    preparedStatement.close();
    connection.close();
}

你可能感兴趣的:(mysql,数据库,jdbc,java,sql)