JDBC的简单了解

JDBC

Java DataBase Connectivity java数据库连接

是一种数据库访问规则规范。

简单使用

基本步骤:

  • 注册driver
  • 建立连接
  • 创建statement对象进行交互
  • 执行sql 获取结果
  • 释放资源

代码举例:

package com;

import java.sql.*;

public class Main {
    public static void main(String[] args) {
        Driver driver;
        Connection connection;
        Statement statement;
        ResultSet res;
        try {
            driver = new com.mysql.cj.jdbc.Driver();
            DriverManager.registerDriver(driver);
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
            statement = connection.createStatement();
            String sql = "select * from product";
            res =  statement.executeQuery(sql);
            while(res.next()) {
                System.out.println("pname: " + res.getString("pname")
                        + "price: " + res.getDouble("price"));
            }
            res.close();
            statement.close();
            connection.close();
        }catch (Exception e) {
            e.printStackTrace();
        }
    }
}

maven依赖添加地址:

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

释放资源代码整理

将释放资源的逻辑可以提出来,写出一个工具类

package com;

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

public class JDBCUtils {

    public static void close(ResultSet res, Statement statement, Connection connection) {
        closeRes(res);
        closeStatement(statement);
        closeConnection(connection);
    }

    public static void closeRes(ResultSet res) {
        try {
            if(res != null) {
                res.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            res = null;
        }
    }

    public static void closeStatement(Statement statement) {
        try {
            if(statement != null) {
                statement.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            statement = null;
        }
    }

    public static void closeConnection(Connection connection) {
        try {
            if(connection != null) {
                connection.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            connection = null;
        }
    }
}

优化之后,上面的例子就可以写成这样:

package com;

import java.sql.*;

public class Main {
    public static void main(String[] args) {
        Driver driver;
        Connection connection = null;
        Statement statement = null;
        ResultSet res = null;
        try {
            driver = new com.mysql.cj.jdbc.Driver();
            DriverManager.registerDriver(driver);
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
            statement = connection.createStatement();
            String sql = "select * from product";
            res =  statement.executeQuery(sql);
            while(res.next()) {
                System.out.println("pname: " + res.getString("pname")
                        + "price: " + res.getDouble("price"));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, statement, connection);// 在finally里去close()
        }
    }
}

关于注册driver的优化

看下源码可以发现其内部有个static代码块:

    static {
        try {
            DriverManager.registerDriver(new Driver()); // 已经注册了一个Driver
        } catch (SQLException var1) {
            throw new RuntimeException("Can't register driver!");
        }
    }

内部已经进行了driver的注册,所以没必要重复注册第二个driver,按照文档中的示例,可以采用Class.forName("com.mysql.jdbc.Driver").newInstance()(其实没必要去newInstance()已经有driver,这个操作浪费空间);

优化过后的代码如下所示:

package com;

import java.sql.*;

public class Main {
    public static void main(String[] args) {
        Driver driver;
        Connection connection = null;
        Statement statement = null;
        ResultSet res = null;
        try {
//            driver = new com.mysql.cj.jdbc.Driver(); // 改用动态加载一个driver类
            Class.forName("com.mysql.cj.jdbc.Driver");
//            DriverManager.registerDriver(driver); // com.mysql.cj.jdbc.Driver内部已经注册过driver了  没必要重复注册
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false", "root", "Admin@123");
            statement = connection.createStatement();
            String sql = "select * from product";
            res =  statement.executeQuery(sql);
            while(res.next()) {
                System.out.println("pname: " + res.getString("pname")
                        + "price: " + res.getDouble("price"));
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, statement, connection);
        }
    }
}

关于Class.forName(className), 在一些应用中,无法事先知道使用者将加载什么类(比如本例中使用jdbc可能是其他数据库),而必须让使用者指定类名称以加载类,可以使用 Class 的静态 forName() 方法实现动态加载类。详见Class.forName

jdbc.properties

上述例子中的数据库配置等信息都是写在代码中的,我们一般是要从配置文件中读取的,所以我们创建一个名为jdbc.properties的文件,如下:

driverClass=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/base1?serverTimezone=GMT&useSSL=false
userName=root
password=Admin@123

然后我们修改JDBCUtils里面的代码:

package com;

import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JDBCUtils {
    static String driverClass = null; // 数据库类型
    static String url = null; // 数据库地址
    static String userName = null;
    static String password = null;

    static { // 默认static代码块  读取properties配置
        try {
            Properties properties = new Properties(); // 获取Properties对象
            InputStream setting = new FileInputStream("src/jdbc.properties"); // 获取文件流
            properties.load(setting);// properties对象加载读取到的配置
            driverClass = properties.getProperty("driverClass"); // 从配置中读取特定的配置
            url = properties.getProperty("url");
            userName = properties.getProperty("userName");
            password = properties.getProperty("password");
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

//    注册驱动并且并且获取连接Connection
    public static Connection getConnection() {
        Connection connection = null;
        try {
            Class.forName(driverClass);
            connection = DriverManager.getConnection(url, userName, password);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            return connection;
        }
    }


//     释放资源
    public static void close(ResultSet res, Statement statement, Connection connection) {
        closeRes(res);
        closeStatement(statement);
        closeConnection(connection);
    }

    public static void closeRes(ResultSet res) {
        try {
            if(res != null) {
                res.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            res = null;
        }
    }

    public static void closeStatement(Statement statement) {
        try {
            if(statement != null) {
                statement.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            statement = null;
        }
    }

    public static void closeConnection(Connection connection) {
        try {
            if(connection != null) {
                connection.close();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            connection = null;
        }
    }
}

JDBC对数据库的CRUD

  • insert
 @Test
    public void testInsert() {
        Connection connection = null;
        Statement statement = null;
        ResultSet res = null;
        try{
            connection =  JDBCUtils.getConnection();
            statement = connection.createStatement();
            String sql = "insert into product values(null, '泡椒凤爪', 3, null, 5);";
            int result = statement.executeUpdate(sql); // 执行insert update  delete的时候使用executeUpdate return int
            if(result > 0) { // result为影响的行数
                System.out.println("insert successfully!");
            }else {
                System.out.println("insert failed");
            }
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, statement, connection);
        }
    }

update和delete同理

使用junit进行单元测试

  1. 添加junit依赖
<!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
  1. 添加一个类,定义测试方法,给其加上@Test注解
import com.JDBCUtils;
import org.junit.Test;

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

public class TestDemo {

    @Test
    public void testQuery() {
        Connection connection = null;
        Statement statement = null;
        ResultSet res = null;
        try{
            connection =  JDBCUtils.getConnection();
            statement = connection.createStatement();
            String sql = "select * from product;";
            res = statement.executeQuery(sql);
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            JDBCUtils.close(res, statement, connection);
        }
    }
}

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

推荐阅读更多精彩内容