美文网首页
数据库(三)2018-08-26

数据库(三)2018-08-26

作者: 迷人的酋长 | 来源:发表于2018-08-29 01:12 被阅读0次
1. JDBC的简介
概述: 就是Java用来操作不同数据库(DBMS)的类库(技术), 本质就是一些类和接口.
    /*
        类: DriverManager
        
        接口: Driver, Connection, Statement, PreparedStatement, ResultSet
    */
    
    //Java Data Base  Connectivity, Java数据库连接(技术).
    
    /*
        集合: 就是Java用来存储不同类型数据的容器, 本质就是一些类和接口.
            接口: Collection, Set, List, Map
            类: ArrayList, HashSet, HashMap
            
            面试题: 请求写代码实现, 模拟栈的数据结构(先进后出)特点?
        
        
        IO流: 就是Java用来传输数据的技术, 本质就是一些类和接口.
            抽象类:    InputStream, OutputStream, Reader, Writer
            
            实现类: FileInputStream, BufferedInputStream, FileReader, BufferedReader
            
        总结: 集合的顶层都是接口, IO流的顶层都是抽象类.
    
    */

核心功能:
    A: 连接数据库.
    B: 向数据库发送SQL语句.
    C: 操作数据库返回的 结果集.
        如果操作的是更新语句(增删改),  返回的结果集是: int 类型
        如果操作的是查询语句,  返回的结果集是: ResultSet 类型
  1. 什么是驱动?
    就是设备间进行通信的桥梁.
  1. JDBC的原理是什么:
    我们知道JDBC是用来操作不同数据库的, 但是操作不同的数据库需要使用不同的驱动.
    eg: 我们想操作MySQL数据库, 就需要安装MySQL的驱动, 我们想操作Oracle数据库, 就需要安装Oracle数据库的驱动, 如果我们操作SQLServer数据库,就需要安装SQLServer数据库的驱动, 这样做是比较麻烦的. 因为Java已经提供了大量的类和接口了, 但是要要求额外记忆一些其他的类和接口, 这样就增加了程序员的学习难度. 后来Sun公司发现了这个问题, 就和各大数据库生产商协商决定, 由Sun公司提供统一的规范(就是一些类和接口), 数据库生产商提供具体的实现. Sun公司提供的这些类和接口就是: JDBC.

4. JDBC的代码演示

A: 创建一个数据库web04.
B: 在数据库web04中创建一个表(users);
    create table users(
        id int primary key auto_increment;
        username varchar(20),
        password varchar(20)
    );
C: 往数据表中添加数据.
    insert into user values(null,'aaa','123');
    insert into user values(null,'bbb','321');
    insert into user values(null,'ccc','456');
    insert into user values(null,'ddd','654');
    
D: 通过JDBC操作表数据.
    1) 导入驱动.
    2) 注册驱动.
    3) 获取连接对象.
    4) 根据连接对象, 获取可以操作SQL语句的对象.
    5) 执行SQL语句, 获取结果集.
        如果操作的是更新语句(增删改),  返回的结果集是: int 类型
        如果操作的是查询语句,  返回的结果集是: ResultSet 类型
    6) 操作结果集.
    7) 释放资源.
5. JDBC的API详解之: DriverManager(类)
作用: 主要用于驱动管理及获取连接对象的.

作用一:    注册驱动.
    //                              MySQL的驱动或者Oracle的驱动
    public static void registerDriver(Driver driver);   //注册驱动的意思, 形参是谁的驱动, 就注册谁.
    
    //Driver类就是MySQL数据库提供的 驱动类
    public class com.mysql.jdbc.Driver implements java.sql.Driver{
        
    }
    
    //记忆: 实际开发中, 我们不用上述的方式注册驱动, 因为上述注册驱动的方式会导致驱动程序注册两次.
    //所以: 我们通过反射的方式加载 com.mysql.jdbc.Driver类的字节码文件, 从而来自动 注册驱动.
    Class.forName("com.mysql.jdbc.Driver");         //驱动类的全路径
    

作用二: 获取连接对象.
    public static Connection getConnection(String url, String username, String password);   //获取连接对象.
    /*
        url: 数据库连接字符串.
            格式:
                大白话:  连接方式:要操作的DBMS://要操作的数据库的IP地址或者主机名:端口号/要操作的具体的数据库
                专业:    协议:子协议:要操作的DBMS://要操作的数据库的IP地址或者主机名:端口号/要操作的具体的数据库
                
            例如:
                jdbc:mysql://127.0.0.1:3306/web04
                jdbc:mysql://localhost:3306/web04
                
                如果操作的是本地数据库(DBMS), 上述的写法可以优化为:
                    jdbc:mysql:///web04
        
        
        username: 要操作的数据库(DBMS)的账号
        
        
        password: 要操作的数据库(DBMS)的密码
    
    */
6. JDBC的API详解之: Connection(接口)
Connection: 连接对象

作用一: 获取可以执行SQL语句的对象.            //掌握
    public Statement createStatement();                     //获取可以执行SQL语句的对象.
    
    public PreparedStatement prepareStatement(String sql);  //获取可以执行SQL语句的对象, 具有预编译功能, 可以解决SQL注入攻击问题.


作用二: 可以进行事务管理.      
    public void setAutoCommit(boolean flag);                //设置是否开启事务的自动提交功能, 相当于我们昨天讲解的: 开启事务.
    public void commit();                                   //提交事务
    public void rollback();                                 //事务回滚
    public void setTransactionIsolation(int level);         //设置事务的隔离级别
    
    
Connection接口中的常量:
    public static final int TRANSACTION_NONE = 0;
    public static final int TRANSACTION_READ_UNCOMMITTED = 1;
    public static final int TRANSACTION_READ_COMMITTED = 2;
    public static final int TRANSACTION_REPEATABLE_READ = 4;
    public static final int TRANSACTION_SERIALIZABLE = 8;
7. JDBC的API详解之: Statement(接口)
Statement: 可以操作SQL语句的对象.

作用一:    执行SQL语句.                //掌握
    public ResultSet executeQuery(String sql);      //执行查询语句
    public int executeUpdate(String sql);           //执行更新语句
    

作用二: 可以执行批处理.               
    //批处理只针对更新语句有效.
    
    public void addBatch(String sql);   //把SQL语句添加到批处理(指令)中.
    public int[] executeBatch();        //执行批处理(指令)
    public void clearBatch();           //清除批出(指令)
    
    
    users:          添加5条数据
    orders:         删除2条数据, 修改4条数据
    orderitem:      添加10条数据, 改3条数据
    exam:           删5条数据
8. JDBC的API详解之: ResultSet(接口)
ResultSet: 执行查询语句后的结果集对象.

public boolean next();  //判断结果集中是否还有数据.     类似于Iterator#hasNext().

public XXX getXxx(int columnIndex);     //根据列的编号, 获取该列的信息, Xxx是数据类型的意思  
public XXX getXxx(String columnName);   //根据列的名字, 获取该列的信息, Xxx是数据类型的意思,  个人建议用这种方式.
    //getInt(), getString(), getObject();
9. JDBC释放资源的优化代码. //重点掌握.
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try {
    //2 alter + enter: 处理异常
    Class.forName("com.mysql.jdbc.Driver");
    //3
    conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
    //4
    stat = conn.createStatement();
    //5
    String sql = "select * from users";
    rs = stat.executeQuery(sql);
    //6
    while (rs.next()) {
        int uid = rs.getInt("uid");
        String username = rs.getString("username");
        String password = rs.getString("password");
        System.out.println(uid + "..." + username + "..." + password);
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    //7
    try {
        if(rs != null) {
            rs.close();     //alt + ↑, 代码的向上移动
            rs = null;      //GC会优先回收null对象.
           // System.out.println(1/0);
            System.out.println("rs 关了");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if (stat != null) {
                stat.close();
                stat = null;
                System.out.println("stat 关了");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (conn != null) {
                    conn.close();
                    conn = null;
                    System.out.println("conn 关了");
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
10. JDBC对表数据的CURD操作
public class Test02_JDBC对数据的CURD操作 {
    //alter + enter: 给出建议   Junit4

    /**
     * JDBC的查
     */
    @Test
    public void method1() {
        System.out.println("JDBC的查, 自己实现");
    }

    /**
     * JDBC的增
     */
    @Test
    public void method2() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 处理异常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "insert Into users values(null,'tianqi','pw567')";
           int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("添加成功");
            } else {
                System.out.println("添加失败");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JDBC的改
     */
    @Test
    public void method3() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 处理异常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "update users set password='777' where uid = 6;";
            int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("修改成功");
            } else {
                System.out.println("修改失败");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * JDBC的删
     */
    @Test
    public void method4() {
        Connection conn = null;
        Statement stat = null;
        try {
            //2 alter + enter: 处理异常
            Class.forName("com.mysql.jdbc.Driver");
            //3
            conn = DriverManager.getConnection("jdbc:mysql:///web04", "root", "123");
            //4
            stat = conn.createStatement();
            //5
            String sql = "delete from users where uid = 6;";
            int num = stat.executeUpdate(sql);
            //6
            if(num > 0) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }
            //7
            stat.close();
            conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
11. JDBCUtils工具类的抽取
方式一: 普通抽取   
    public class JDBCUtils {
        //1. 构造私有.
        
        //2. 注册驱动, 静态代码块实现.
        
        //3. 获取连接对象.
        
        //4. 释放资源.    try-catch-finally 语句的嵌套实现.
    }
    
    此时, 虽然我们已经成功的抽取出来了JDBCUtils工具类, 但是和一个开发原则相违背"对修改关闭, 对扩展开放".
    例如: 如果我们想操作web05这个数据库了, 就得修改工具类中url的写法, 如果我们操作的数据库的用户名和密码
    改变了, 我们也得修改工具类中username,password的写法, 这样做扩展性较差.

    于是, 我们就想着如何解决这个问题?
    
    能不能创建一个文件(配置文件), 里边记录的是各项配置信息, 然后由工具类读取该配置文件的信息即可.
    这个配置文件就是:  **.properties
    
    
    Properties集合类:
        概述:  它是一个双列集合, 键值都是String类型, 它是Hashtable集合的子类.
                //Properties集合是唯一可以直接和IO流相结合使用的集合类.
                //它可以直接从流中读取数据, 也可以直接写数据到流中.
                
        成员方法:
            public void load(InputStream is);           //从流中读取数据
            public void load(Reader r);                 //从流中读取数据
            
            public void store(OutputStream os);         //写数据到流中
            public void store(Writer w);                //写数据到流中
            
            public String getProperty(String key);              //根据键获取值
            public void setProperty(String key,String value);   //设置键值对
        
        
        
    
        面试题:
            Hashtable和HashMap的区别?
                HashMap: 线程不安全, 效率高, 可以存null值和null键.
                         JDK1.2出来来.
                Hashtable: 线程安全, 效率低. 不可以存null值和null键.
                         JDK1.0出来的.
                整个Java命名规范是从: JDK1.2开始完善的.


方式二: 结合配置文件的使用
    public class JDBCUtils {
        //1. 构造私有.
        
        //2. 定义变量, 记录配置文件的信息.
        
        //3. 读取配置文件, 并将读取到的值赋值给变量.
        
        //4. 注册驱动, 静态代码块实现.
        
        //5. 获取连接对象.
        
        //6. 释放资源.    try-catch-finally 语句的嵌套实现.
    }
12. SQL注入攻击问题
概述:


代码演示SQL注入攻击问题:


解决方案: PreparedStatement接口的预编译, 占位符.

今日总结:

1. JDBC的原生态代码.
    
2. JDBC的优化释放资源的代码
    
3. Properties的使用
    
4. 抽取JDBCUtils工具类
    
5. 解决SQL注入攻击问题

相关文章

  • 2018-08-26

    2018-08-26 陈顺富简书作者 2018-08-26 09:28 打开App 部门:三分厂 岗位:真空常白班...

  • 2018-08-26

    2018-08-26 现在立刻马上 2018-08-26 20:53 · 字数 599 · 阅读 0 · 日记本 ...

  • 数据库(三)2018-08-26

    1. JDBC的简介 什么是驱动?就是设备间进行通信的桥梁. JDBC的原理是什么:我们知道JDBC是用来操作不同...

  • 付出不亚于任何人的努力

    戴师傅 2018-08-26 2018-08-26 20:32 打开App (稻盛哲学学习会)打卡第122天 姓名...

  • 小程序学习第8天

    2018-08-26昨天没学,空白。

  • 2018-08-26周检视

    20180819-0826周检视 刘挥 2018-08-26 一、本周总结 1.运动:跑步7.43公里+平板支撑三...

  • 爱你的人,不会这样发朋友圈

    作者:猫三 2018-08-26 昨天听友 @文若是个小太阳 留言问猫三,男朋友从来不在朋友圈秀恩爱,觉得特别不是...

  • 论站桩的“阳紧阴松”

    古御养生2018-08-26 很多天没有记录自己的练功感悟了,集训回来之后忙着辅导视频学员的练习,又去三清山风景区...

  • 2018-08-27

    【59号-张玉-如何学习读后总结】 2018-08-26 22:09 · 字数 594 · 阅读 2 · 日记本 ...

  • 2018-08-26

    2018-08-26 事件:今天参加以前同事孩子的婚礼。 感受:惊叹,感动。 对方:欣喜,开心,激动。 想法:时间...

网友评论

      本文标题:数据库(三)2018-08-26

      本文链接:https://www.haomeiwen.com/subject/krgcwftx.html