7.21 JDBC 学习总结

谦虚其心,宏大其量

上午主要学习了JDBC

JDBC(Java DataBase Connectivity,即java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

(JDBC用socket技术实现 是典型的两个进程之间的通信)

JDBC用途

基于昨天学的MySQL知识
http://www.jianshu.com/p/c98059693e5d

在itcast数据库中建立的student表:

student表.png

在MyEclispse中建立Web项目:

2017-07-21 (1).png
2017-07-21 (2).png

下载老师给的mysql-connector-java-5.1.30.jar文件
http://pan.baidu.com/s/1bp1tb7h
(用于连接java和mysql数据库关键文件)

选中文件 (左上角):


2017-07-21 (3).png

复制文件后直接粘贴到 Web工程中WebRoot\WEB-INF\lib文件夹下:

QQ图片20170721113313.png

安装的MySQL数据库为服务器端(左)
打开的MySQL命令行是客户端程序(右):


QQ图片20170721204246.png

我们在客户端(shell)下输入指令:


QQ图片20170721204647.png

传给MySQL服务器端后 其接收指令——解释指令——执行指令——返回给shell结果

Java 所有的API都是为了让我们方便编程设计的,让程序员不用再去考虑很复杂的问题,但要知道其原理! JDBC就是一种用于执行SQL语句的Java API。

使用JDBC来操作数据库用到的类:
1 Connection 连接 (接头人)
2 Statement 语句 (送信的)
3 ResultSet 结果集 (查询需要)

连接遍历数据库的大致步骤:

遍历数据库

遍历打印数据库中数据 代码:

import java.sql.DriverManager;
import java.sql.ResultSet;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;

public class TestJDBC {
    public static void main(String[] args) throws Exception {
        // 第一步 先加载注册JDBC的驱动类
        Class.forName("com.mysql.jdbc.Driver");
        // 第二步 提供JDBC连接的url
        String url = "jdbc:mysql://localhost:3306/itcast";
        String username = "root";
        String password = "root";
        // 第三步 创建数据库的连接(利用驱动器管理器DriverManager的getConnection方法)
        Connection conn = (Connection) DriverManager.getConnection(url, username, password);
        // 第四步 创建一个statement对象
        Statement stmt = (Statement) conn.createStatement();
        // 第五步 执行sql语句
        ResultSet rs = stmt.executeQuery("select * from student");
        // 第六步 循环遍历处理结果
        while(rs.next()) {
            System.out.println(rs.getString("name"));
            System.out.println(rs.getFloat("grade"));
        }
        // 第七步 关闭JDBC对象
        rs.close();
        stmt.close();
        conn.close();
    }
}

注:
第一步 加载注册JDBC的驱动类 Class.forName("com.mysql.jdbc.Driver"); 不同数据库不一样(这里用的是mysql) 需要其他数据库的话 直接去查即可

stmt.executeQuery 返回一个结果集 用于查询

关键语句:

ResultSet rs = stmt.executeQuery("select * from student");

另外要注意第七步关闭顺序(反着来)

上面代码版本异常处理为main函数处抛出:

public static void main(String[] args) throws Exception { }

这种做法不好,若后面代码中间一旦异常停止
则其后面的代码不会执行。

改进的版本:(增加try catch)

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args) {
    
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            stmt = conn.createStatement();
            // 第五步 执行sql语句 获取结果集合
            rs = stmt.executeQuery("select * from student");
            // 第六步 循环遍历结果集 处理
            while(rs.next()) {
                System.out.println(rs.getString("name"));
                System.out.println(rs.getFloat("grade"));
            }
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志操作
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第七步 关闭JDBC对象 释放资源
                rs.close();
                stmt.close();
                conn.close();
            }catch(SQLException e) {
                e.printStackTrace();
            }
            
        }
    }
}

首先是try后两个catch分支 分别处理不同异常,try catch后的finally里执行关闭JDBC对象操作(此更符合事件处理逻辑)

又考虑到对象rs stmt为空关闭会导致异常
改进finally中处理办法:

...
}finally{
    try{
        // 第七步 关闭JDBC对象
        if(rs != null) {
            rs.close();
        }
        if(stmt != null) {
            stmt.close();
        }
        if(conn != null) {
            conn.close();
        }
    }catch(SQLException e) {
        e.printStackTrace();
    }
}

最终较完美代码:

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args) {
    
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            stmt = conn.createStatement();
            // 第五步 执行sql语句
            rs = stmt.executeQuery("select * from student");
            // 第六步 循环遍历处理结果
            while(rs.next()) {
                System.out.println(rs.getString("name"));
                System.out.println(rs.getFloat("grade"));
            }
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入异常操作
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第七步 关闭JDBC对象 释放资源
                if(rs != null) {
                    rs.close();
                }
                if(stmt != null) {
                    stmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
            
        }
    }
}

也可以再优化一下结构:

import java.sql.*;

public class TestJDBC22 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        String Driver = "com.mysql.jdbc.Driver";
        // 对应 第二步 
        String url = "jdbc:mysql://localhost:3306/itcast";
        String username = "root";
        String password = "root";
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName(Driver);
            // 第二步 提供JDBC连接的url
            
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            stmt = conn.createStatement();
            // 第五步 执行sql语句
            rs = stmt.executeQuery("select * from student");
            // 第六步 循环遍历处理结果
            while(rs.next()) {
                System.out.println(rs.getString("name"));
                System.out.println(rs.getFloat("grade"));
            }
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入异常操作
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第七步 关闭JDBC对象 释放资源
                if(rs != null) {
                    rs.close();
                }
                if(stmt != null) {
                    stmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
            
        }
    }
}

重要说明:
将:

import java.sql.DriverManager;
import java.sql.ResultSet;
import com.mysql.jdbc.Connection;
import com.mysql.jdbc.Statement;
...

改为:

import java.sql.*;
...

则代码中很多不用强转类型:

强转说明.png

不遍历的话 则大致步骤:


步骤

数据插入操作代码:

import java.sql.*;

public class Test {
    public static void main(String[] args) {
    
        Connection conn = null;
        Statement stmt = null;
 
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            stmt = conn.createStatement();
            // 第五步 执行sql语句
            String sql = "insert into student values(0,'七月',23,'男')";
            stmt.executeUpdate(sql);
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志等操作 所以要分开两个异常类别 都要 catch 
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第六步 关闭JDBC对象
                if(stmt != null) {
                    stmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

数据添加成功.png

批量插入方法:

import java.sql.*;

public class Test {
    public static void main(String[] args) {
    
        Connection conn = null;
        Statement stmt = null;
 
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            stmt = conn.createStatement();
            // 第五步 执行sql语句
            String sql = "insert into student values(0,'七月1',23,'男')";
            String sq2 = "insert into student values(0,'八月1',32,'男')";
            stmt.addBatch(sql);
            stmt.addBatch(sq2);
            stmt.executeBatch();
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志等操作 所以要分开两个异常类别 都要 catch 
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第六步 关闭JDBC对象
                if(stmt != null) {
                    stmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

此方法中关键语句:

     // 执行sql语句
     String sql = "insert into student values(0,'七月1',23,'男')";
     String sq2 = "insert into student values(0,'八月1',32,'男')";
     stmt.addBatch(sql);
     stmt.addBatch(sq2);
     stmt.executeBatch();

用Statement对象中的addBatch() 函数方法将SQL命令语句都添加到Batch中 然后用executeBatch() 方法整体将Batch 中的语句提交给数据库管理系统。

添加两条数据成功:


添加两条数据成功.png

注:
我们可以使用Statement对象用来做测试 但是在生产环境下一定要考虑使用 PreparedStatement(见下)


下午

学习了 PreparedStatement 对象,用其可以使得update数据更灵活:

import java.sql.*;

public class Test {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement pstmt = null;
        
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            String sql = "insert into student values(?,?,?,?)";
            pstmt = conn.prepareStatement(sql);
            // 第五步 执行sql语句
            pstmt.setInt(1,8);
            pstmt.setString(2,"nihao");
            pstmt.setFloat(3, 55);
            pstmt.setString(4,"男");
            
            pstmt.executeUpdate();
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志等操作 所以要分开两个异常类别 都要 catch 
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第六步 关闭JDBC对象
                if(pstmt != null) {
                    pstmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

PreparedStatement 批量insert数据:

import java.sql.*;

public class TestJDBC {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement pstmt = null;

        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            String sql = "insert into student values(?,?,?,?)";
            pstmt = conn.prepareStatement(sql);
            // 第五步 执行sql语句
            pstmt.setInt(1,9);
            pstmt.setString(2,"9");
            pstmt.setFloat(3, 55);
            pstmt.setString(4,"男");
            pstmt.addBatch();
            
            pstmt.setInt(1,10);
            pstmt.setString(2,"10");
            pstmt.setFloat(3, 68);
            pstmt.setString(4,"男");
            pstmt.addBatch();
            
            pstmt.executeBatch();
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志等操作 所以要分开两个异常类别 都要 catch 
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第六步 关闭JDBC对象
                if(pstmt != null) {
                    pstmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

PreparedStatement 查询:

import java.sql.*;

public class Test {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        
        try{
            // 第一步 先加载JDBC的驱动类
            Class.forName("com.mysql.jdbc.Driver");
            // 第二步 提供JDBC连接的url
            String url = "jdbc:mysql://localhost:3306/itcast";
            String username = "root";
            String password = "root";
            // 第三步 创建数据库的连接
            conn = DriverManager.getConnection(url, username, password);
            // 第四步 创建一个statement对象
            String sql = "select * from student";
            pstmt = conn.prepareStatement(sql);
            // 第五步 执行sql语句 获取结果集合
            rs = pstmt.executeQuery();
            // 第六步 循环遍历处理结果
            while(rs.next()){
                System.out.println(rs.getInt("id"));
                System.out.println(rs.getString("name"));
                System.out.println(rs.getInt("age"));
            }
        }catch(ClassNotFoundException e) {
            e.printStackTrace();
            System.out.println("ClassNotFoundException");
            // 还要进行写入日志等操作 所以要分开两个异常类别 都要 catch 
        }catch(SQLException e) {
            e.printStackTrace();
            System.out.println("SQLException");
        }finally{
            try{
                // 第七步 关闭JDBC对象
                if(pstmt != null) {
                    pstmt.close();
                }
                if(conn != null) {
                    conn.close();
                }
            }catch(SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

注意PreparedStatement 和 Statement 创建一个statement对象(第4步) 和 执行sql语句(第5步)语句的区别:

Statement:

String sql = "select * from student";
// 第四步 创建一个statement对象
stmt = conn.createStatement();
// 第五步 执行sql语句
rs = stmt.executeQuery(sql);

PreparedStatement:

String sql = "select * from student";
// 第四步 创建一个statement对象
pstmt = conn.prepareStatement(sql);
// 第五步 执行sql语句 获取结果集合
rs = pstmt.executeQuery();

PreparedStatement优势绝不仅仅是更灵活的参数化查询
请参见:PreparedStatement VS Statement


拓展阅读:

1 - 通过JDBC进行简单的增删改查(以MySQL为例)
2 - JDBC详解

世界上所有的追求都是因为热爱
一枚爱编码 爱生活 爱分享的IT信徒
— hongXkeX

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

推荐阅读更多精彩内容

  • JDBC概述 在Java中,数据库存取技术可分为如下几类:JDBC直接访问数据库、JDO技术、第三方O/R工具,如...
    usopp阅读 3,522评论 3 75
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,505评论 18 399
  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,398评论 0 4
  • 西江月三首 胭脂雪 西江月·整装待发游长隆 场上妖娆舞曲,耳边缱绻清风。曦阳明净照欢容,更有鸣蝉相送。 往寄多情山...
    胭脂雪er阅读 415评论 0 0
  • 1、let, const, class, extends, super, arrow functions, tem...
    逍遥g阅读 392评论 0 1