018.用户session分析:JDBC原理介绍以及增删改查示范

JDBC原理

1、
Java程序/J2EE程序,当需要操作数据库,通常就是对数据库中某一个,或者某些表,进行增删改查
那么就需要通过某些方式连接到数据库,比如MySQL,执行各种SQL语句(insert、select、udpate)
2、
JDBC,Java Database Connectivity,Java数据库连接技术。
JDBC,其实只是代表了JDK提供的一套面向数据库的一套开发接口,注意,这里大部分仅仅是接口而已
换句话说,你的Java应用程序,光有JDBC,是操作不了数据库的,更不用谈所谓的CRUD,增删改查。
因为JDBC只是一套接口,接口,接口而已
JDBC真正的意义在于通过接口统一了java程序对各种数据库的访问的规范
3、
数据库厂商提供的JDBC驱动,JDBC Driver。
数据库厂商,比如说,MySQL公司,或者Oracle公司,会针对JDBC的一套接口,提供完整的一套接口的实现类
在这套实现类中,不同的数据库厂商就实现了针对自己数据库的一套连接、执行SQL语句等等实际的功能
4、
MySQL数据库

JdbcCRUD.java


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

/**
 * JDBC增删改查示范类
 * 
 * JDBC只是java程序操作数据库中最原始和最基础的一种方式
 * 
 * 实际上,在项目中,我们一般不会直接使用JDBC;而是会使用J2EE的一些开源框架,比如MyBatis,也可以是Hibernate
 * 而且为了方便框架的整合使用,我们通常都会在spark作业中,使用Spring开源框架,进行各种技术的整合
 * 比如Kafka、Redis、ZooKeeper、Thrift
 * 
 * MyBatis/Hibernate这种操作数据库的框架,其实底层也是基于JDBC进行封装的,只不过提供了更加方便快捷的使用
 * 大大提升了我们的开发效率
 * 
 * 但是在本套系类课程中,是不会使用这些开源框架来操作数据库的,而只会使用JDBC
 * 因为直接用JDBC最简单,也最基础,不需要其他技术的基础
 * 主要同学们有基本的java编程基础、最最基础的hadoop基础知识,以及扎实的Spark技术功底
 * 我们就要保证同学们就可以学习这套高端、负责的Spark大型大数据项目实战课程
 * 
 * @author Administrator
 *
 */
@SuppressWarnings("unused")
public class JdbcCRUD {

    public static void main(String[] args) {
//      insert();
//      update();
//      delete();
//      select();
        preparedStatement();
    }
    
    /**
     * 测试插入数据
     */
    private static void insert() {
        // 总结一下JDBC的最基本的使用过程
        // 1、加载驱动类:Class.forName()
        // 2、获取数据库连接:DriverManager.getConnection()
        // 3、创建SQL语句执行句柄:Connection.createStatement()
        // 4、执行SQL语句:Statement.executeUpdate()
        // 5、释放数据库连接资源:finally,Connection.close()
        
        // 定义数据库连接对象
        // 引用JDBC相关的所有接口或者是抽象类的时候,必须是引用java.sql包下的
        // java.sql包下的,才代表了java提供的JDBC接口,只是一套规范
        // 至于具体的实现,则由数据库驱动来提供,切记不要引用诸如com.mysql.jdbc包的类
        Connection conn = null;
        
        // 定义SQL语句执行句柄:Statement对象
        // Statement对象,其实就是底层会基于Connection数据库连接
        // 可以让我们方便的针对数据库中的表,执行增删改查的SQL语句
        // 比如insert、udpate、delete和select语句
        Statement stmt = null;
        
        try {
            // 第一步,加载数据库的驱动,我们都是面向java.sql包下的接口在编程,所以
            // 要想让JDBC代码能够真正操作数据库,那么就必须第一步先加载进来你要操作的数据库的驱动类
            // 使用Class.forName()方式来加载数据库的驱动类
            // Class.forName()是Java提供的一种基于反射的方式,直接根据类的全限定名(包+类)
            // 从类所在的磁盘文件(.class文件)中加载类对应的内容,并创建对应的Class对象
            Class.forName("com.mysql.jdbc.Driver");  
            
            // 获取数据库的连接
            // 使用DriverManager.getConnection()方法获取针对数据库的连接
            // 需要给方法传入三个参数,包括url、user、password
            // 其中url就是有特定格式的数据库连接串,包括“主协议:子协议://主机名:端口号//数据库”
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/spark_project", 
                    "root", 
                    "root");  
            
            // 基于数据库连接Connection对象,创建SQL语句执行句柄,Statement对象
            // Statement对象,就是用来基于底层的Connection代表的数据库连接
            // 允许我们通过java程序,通过Statement对象,向MySQL数据库发送SQL语句
            // 从而实现通过发送的SQL语句来执行增删改查等逻辑
            stmt = conn.createStatement();
            
            // 然后就可以基于Statement对象,来执行insert SQL语句了
            // 插入一条数据
            // Statement.executeUpdate()方法,就可以用来执行insert、update、delete语句
            // 返回类型是个int值,也就是SQL语句影响的行数
            String sql = "insert into test_user(name,age) values('李四',26)";  
            int rtn = stmt.executeUpdate(sql);    
            
            System.out.println("SQL语句影响了【" + rtn + "】行。");  
        } catch (Exception e) {
            e.printStackTrace();  
        } finally {
            // 最后一定要记得在finally代码块中,尽快在执行完SQL语句之后,就释放数据库连接
            try {
                if(stmt != null) {
                    stmt.close();
                } 
                if(conn != null) {
                    conn.close();  
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    
    /**
     * 测试更新数据
     */
    private static void update() {
        Connection conn = null;
        Statement stmt = null;
        
        try {
            Class.forName("com.mysql.jdbc.Driver");  
            
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/spark_project", 
                    "root", 
                    "root"); 
            stmt = conn.createStatement();
            
            String sql = "update test_user set age=27 where name='李四'";
            int rtn = stmt.executeUpdate(sql);
            
            System.out.println("SQL语句影响了【" + rtn + "】行。");  
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(stmt != null) {
                    stmt.close();
                } 
                if(conn != null) {
                    conn.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace(); 
            }
        }
    }
    
    /**
     * 测试删除数据
     */
    private static void delete() {
        Connection conn = null;
        Statement stmt = null;
        
        try {
            Class.forName("com.mysql.jdbc.Driver");  
            
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/spark_project", 
                    "root", 
                    "root"); 
            stmt = conn.createStatement();
            
            String sql = "delete from test_user where name='李四'";
            int rtn = stmt.executeUpdate(sql);
            
            System.out.println("SQL语句影响了【" + rtn + "】行。");  
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(stmt != null) {
                    stmt.close();
                } 
                if(conn != null) {
                    conn.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace(); 
            }
        }
    }
    
    /**
     * 测试查询数据
     */
    private static void select() {
        Connection conn = null;
        Statement stmt = null;
        // 对于select查询语句,需要定义ResultSet
        // ResultSet就代表了,你的select语句查询出来的数据
        // 需要通过ResutSet对象,来遍历你查询出来的每一行数据,然后对数据进行保存或者处理
        ResultSet rs = null;
        
        try {
            Class.forName("com.mysql.jdbc.Driver");  
            
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/spark_project", 
                    "root", 
                    "root"); 
            stmt = conn.createStatement();
            
            String sql = "select * from test_user";
            rs = stmt.executeQuery(sql);
            
            // 获取到ResultSet以后,就需要对其进行遍历,然后获取查询出来的每一条数据
            while(rs.next()) {
                int id = rs.getInt(1);
                String name = rs.getString(2);
                int age = rs.getInt(3);
                System.out.println("id=" + id + ", name=" + name + ", age=" + age);    
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(stmt != null) {
                    stmt.close();
                } 
                if(conn != null) {
                    conn.close();  
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    
    /**
     * 测试PreparedStatement
     */
    private static void preparedStatement() {
        Connection conn = null;
        /**
         * 如果使用Statement,那么就必须在SQL语句中,实际地去嵌入值,比如之前的insert语句
         * 
         * 但是这种方式有一个弊端,第一,是容易发生SQL注入,SQL注入,简单来说,就是,你的网页的用户
         * 在使用,比如论坛的留言板,电商网站的评论页面,提交内容的时候,可以使用'1 or 1',诸如此类的
         * 非法的字符,然后你的后台,如果在插入评论数据到表中的时候,如果使用Statement,就会原封不动的
         * 将用户填写的内容拼接在SQL中,此时可能会发生对数据库的意外的损坏,甚至数据泄露,这种情况就叫做
         * SQL注入
         * 
         * 第二种弊端,就是性能的低下,比如insert into test_user(name,age) values('张三',25)
         * insert into test_user(name,age) values('李四',26)
         * 其实两条SQL语句的结构大同小异,但是如果使用这种方式,在MySQL中执行SQL语句的时候,却需要对
         * 每一条SQL语句都实现编译,编译的耗时在整个SQL语句的执行耗时中占据了大部分的比例
         * 所以,Statement会导致执行大量类似SQL语句的时候的,性能低下
         * 
         * 如果使用PreparedStatement,那么就可以解决上述的两个问题
         * 1、SQL注入,使用PreparedStatement时,是可以在SQL语句中,对值所在的位置使用?这种占位符的
         * 使用占位符之后,实际的值,可以通过另外一份放在数组中的参数来代表。此时PreparedStatement会对
         * 值做特殊的处理,往往特殊处理后,就会导致不法分子的恶意注入的SQL代码失效
         * 2、提升性能,使用PreparedStatement之后,其实结构类似的SQL语句,都变成一样的了,因为值的地方
         * 都会变成?,那么一条SQL语句,在MySQL中只会编译一次,后面的SQL语句过来,就直接拿编译后的执行计划
         * 加上不同的参数直接执行,可以大大提升性能
         */
        PreparedStatement pstmt = null;
        
        try {
            Class.forName("com.mysql.jdbc.Driver");  
            
            conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/spark_project?characterEncoding=utf8", 
                    "root", 
                    "root");  
            
            // 第一个,SQL语句中,值所在的地方,都用问好代表
            String sql = "insert into test_user(name,age) values(?,?)";
            
            pstmt = conn.prepareStatement(sql);
            
            // 第二个,必须调用PreparedStatement的setX()系列方法,对指定的占位符设置实际的值
            pstmt.setString(1, "李四");  
            pstmt.setInt(2, 26);  
            
            // 第三个,执行SQL语句时,直接使用executeUpdate()即可,不用传入任何参数
            int rtn = pstmt.executeUpdate();    
            
            System.out.println("SQL语句影响了【" + rtn + "】行。");  
        } catch (Exception e) {
            e.printStackTrace();  
        } finally {
            try {
                if(pstmt != null) {
                    pstmt.close();
                } 
                if(conn != null) {
                    conn.close();  
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }
    
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容