Java与数据库的桥梁:JDBC使用详解

JDBC

在这篇文章中,我们将深入探讨JDBC(Java Database Connectivity)的核心概念和实际应用。

你将了解如何通过JDBC实现数据库的连接、操作和管理,从而使你的Java应用程序与各种数据库无缝对接。

无论是执行SQL查询、处理结果集,还是处理事务,我们将逐步解析每个环节,提供实用示例和最佳实践。

掌握JDBC不仅能提升你的数据操作能力,更能为你的项目带来更高的灵活性和效率,让我们一起揭开这一强大工具的面纱,开启你的数据库编程之旅!

JDBC简介

为了便于程序保存和读取数据,而且能直接通过条件快速查询大指定的数据,就出现了数据库(Datebase)这种专门用于集中存取和查询的软件。

JDBC是Java程序访问数据库的标准接口。

使用Java程序访问数据库时,Java代码并不是直接通过TCP连接去访问数据库,而是通过JDBC接口来访问数据库的,而JDBC接口则通过JDBC驱动来实现真正对数据库的访问。

JDBC接口是Java标准库自带的,具体的JDBC驱动是由数据库厂商提供的从代码上来看,JDBC就是定义了一组接口,某个具体的JDBC驱动就是实现这些JDBC接口的类。

MySQL的JDBC驱动就是一个jar包,它本身也是纯Java编写的。我们只需要引入这个JDBC驱动的jar包就可以正常访问MySQL服务器。

我们自己编写的代码只需要引用Java标准库提供的java.sql包下面的相关接口,就可以间接地通过JDBC驱动jar包,通过网络,来访问MySQL服务器了,所有的复杂的网络通讯也都被封装到了JDBC驱动中。

现在Maven的依赖最新版本号是8.0.33。

</dependency>        <dependency>            <groupId>mysql</groupId>            <artifactId>mysql-connector-java</artifactId>            <version>8.0.33</version>            <scope>runtime</scope></dependency>

JDBC连接

Connection

Connection代表一个JDBC连接,它相当于Java程序到数据库的连接(通常是TCP连接)。

打开一个Connection时,需要准备URL、用户名和密码,才能成功连接到数据库。

核心代码

核心代码是DriverManager提供的静态方法getConnection()。

DriverManager会自动扫描classpath,找到所有的JDBC驱动,然后根据我们传入的URL自动挑选一个合适的驱动。

因为JDBC连接是一种昂贵的资源,所以使用后要及时释放,所以使用try (resource)来自动释放。

class Main{    public static void main(String[] args) throws SQLException {        String JDBC_URL = "jdbc:mysql://localhost:3306/learnjdbc?useSSL=false&serverTimezone=UTC";//要连接已创建的数据库,我这个test数据库是已经创建好的。        String JDBC_USER = "root";//root是默认的超级用户        String JDBC_PASSWORD = "11111111";//自定义密码,千万设置完别忘了        Connection conn = null;        try {            // 获取连接            conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);            System.out.println("连接成功!");            // TODO: 访问数据库...        } catch (SQLException e) {            e.printStackTrace();        } finally {            // 关闭连接            if (conn != null) {                try {                    conn.close();                } catch (SQLException e) {                    e.printStackTrace();                }            }        }    }}

JDBC查询

代码步骤:

1.通过Connection提供的createStatement()方法创建一个Statement对象,用于执行一个查询;

2.执行Statement对象提供的executeQuery("SELECT * FROM students")并传入SQL语句,执行查询并获得返回的结果集,使用ResultSet来引用这个结果集;

3.反复调用ResultSet的next()方法并读取每一行结果。

注意:

因为Connection、Statement、ResultSet都是许哟啊关闭的资源,所以需要嵌套使用try,确保即时关闭,所以显得繁琐。

ResultSet获取列时,是从1开始的。

ResultSet获取列时,必须根据select的列对应的位置调用getLong()、getString()这些方法,否则对应位置的数据类型不对,将报错。

        Connection conn = null;        try {            // 获取连接            conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);            System.out.println("连接成功!");            // TODO: 访问数据库...            Statement statement=null;            try {                statement = conn.createStatement();                ResultSet result=null;                try {                    result = statement.executeQuery("select * from students");                    while (result.next()){                        long id=result.getLong(1);                        String name=result.getString(2);                        long gender=result.getLong(3);                        long grade=result.getLong(4);                        int score=result.getInt(5);                        System.out.println(id+" "+name+" "+gender+" "+grade+" "+score);                    }                } catch (SQLException e) {                    throw new RuntimeException(e);                } finally {                    if (result!=null)                        try {                            result.close();                        } catch (SQLException e) {                            throw new RuntimeException(e);                        }                }            } catch (SQLException e) {                throw new RuntimeException(e);            } catch (RuntimeException e) {                throw new RuntimeException(e);            }        } catch (SQLException e) {            e.printStackTrace();        } finally {            // 关闭连接            if (conn != null) {                try {                    conn.close();                } catch (SQLException e) {                    e.printStackTrace();                }            }        }

SQL注入

为了避免SQL注入攻击,和statement拼接字符串非常容易引发SQL注入问题。

所以使用Java对数据库进行操作时,必须使用PreparedStatement,严禁任何通过参数拼字符串的代码!!!!

            // TODO: 访问数据库...            PreparedStatement ps=null;            ps = conn.prepareStatement("select * from students where id>? and score>=?");            ps.setObject(1,2);            ps.setObject(2,60);            ResultSet result=null;            result=ps.executeQuery();            while (result.next()){                long id=result.getLong(1);                String name=result.getString(2);                long gender=result.getLong(3);                long grade=result.getLong(4);                int score=result.getInt(5);                System.out.println(id+" "+name+" "+gender+" "+grade+" "+score);            }

数据类型

使用JDBC的时候,我们需要在Java数据类型和SQL数据类型之间进行转换。JDBC在java.sql.Types定义了一组常量来表示如何映射SQL数据类型。

JDBC的增删改查

// TODO: 访问数据库...PreparedStatement ps=null;            ps = conn.prepareStatement("select * from students where id>? and score>=?");            ps.setObject(1,2);            ps.setObject(2,60);            ResultSet result=null;            result=ps.executeQuery();            while (result.next()){                long id=result.getLong(1);                String name=result.getString(2);                long gender=result.getLong(3);                long grade=result.getLong(4);                int score=result.getInt(5);                System.out.println(id+" "+name+" "+gender+" "+grade+" "+score);            }

// TODO: 访问数据库...            PreparedStatement ps=null;            ps=conn.prepareStatement("INSERT INTO students (grade, name, gender,score) VALUES (?,?,?,?)",Statement.RETURN_GENERATED_KEYS);            ps.setObject(1, 1); // grade            ps.setObject(2, "olderhard"); // name            ps.setObject(3, 1); // gender            ps.setObject(4, 90); // score            int n = ps.executeUpdate();            ResultSet result=null;            result=ps.getGeneratedKeys();            if (result.next()){                System.out.println(result.getLong(1));            }

// TODO: 访问数据库...            PreparedStatement ps=null;            ps=conn.prepareStatement("UPDATE students SET name=? WHERE id=?");            ps.setObject(1,"bob");            ps.setObject(2,14);            iint n=ps.executeUpdate();

// TODO: 访问数据库...            PreparedStatement ps=null;            ps=conn.prepareStatement("DELETE FROM students WHERE id=?");            ps.setObject(1,15);            int n=ps.executeUpdate();

JDBC事务

数据库事务时由若干个SQL语句构成的一个操作序列。数据库系统保证在一个事务中所有SQL要么全部执行成功,要么全部不执行,即数据库事务具有ACID特性,原子性,一致性,隔离性,持久性。

要在JDBC中执行事务,本质上就是如何把多条SQL包裹在一个数据库事务中执行。

注意关键点即可:连接成功后;conn.setAutoCommit(false);之后对数据库操作完成后;就conn.commit(),提交事务;再加一个异常回滚conn.rollback()。

Connection conn = null;        PreparedStatement p1=null;        PreparedStatement p2=null;        try {            // 获取连接            conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);            System.out.println("连接成功!");            conn.setAutoCommit(false);  //关闭自动提交模式            // TODO: 一系列对数据库的操作...            conn.commit();  //提交事务        } catch (SQLException e) {            if(conn!=null){                try {                    conn.rollback();                    System.out.println("Transaction rolled back.");                } catch (SQLException ex) {                    throw new RuntimeException(ex);                }            }        }

JDBC批处理

在JDBC代码中,我们可以利用SQL数据库的特性,把同一个SQL但参数不同的若干次操作合并为一个batch执行。

使用JDBC的batch操作会大大提高执行效率,对内容相同,参数不同的SQL,要优先考虑batch操作。

// TODO: 访问数据库...            PreparedStatement ps=null;            ps=conn.prepareStatement("INSERT INTO students (name, gender, grade, score) VALUES (?, ?, ?, ?)");            for (Student s : students) {                ps.setString(1, s.name);                ps.setBoolean(2, s.gender);                ps.setInt(3, s.grade);                ps.setInt(4, s.score);                ps.addBatch(); // 添加到batch            }            // 执行batch:            int[] ns = ps.executeBatch();            for (int n : ns) {                System.out.println(n + " inserted."); // batch中每个SQL执行的结果数量            }

JDBC连接池

与多线程的线程池原因类似,在执行JDBC的增删改查的操作时,如果每一次操作都来一次打开连接,操作,关闭连接。那么创建和销毁JDBC连接的开销就太大了。为了避免频繁地创建和销毁JDBC连接,我们可以通过连接池复用已经创建好的连接。

JDBC连接池有一个标准的接口javax.sql.DataSource,要使用JDBC连接池,我们必须选择一个JDBC连接池的实现。

常用的JDBC连接池有:HikariCP、C3P0、BoneCP、Druid

之后我们通过创建一个DATa Source实例(对象),这个就是连接池。

HikariConfig config = new HikariConfig();config.setJdbcUrl("jdbc:mysql://localhost:3306/test");config.setUsername("root");config.setPassword("password");config.addDataSourceProperty("connectionTimeout", "1000"); // 连接超时:1秒config.addDataSourceProperty("idleTimeout", "60000"); // 空闲超时:60秒config.addDataSourceProperty("maximumPoolSize", "10"); // 最大连接数:10DataSource ds = new HikariDataSource(config);

如何使用连接池?

类似这个

conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);

这样使用

conn = config.getConnection();
#Java##数据库##Java后端#
Java面试题 文章被收录于专栏

本专栏汇总了大量的Java面试题和Java面经,希望对大家有所帮助!

全部评论

相关推荐

卡卡罗特ovo:说起云智我就来气,约好了一面,结果面试官没来,ssob上问hr也未读,我还是专门请了半天假在家面试,恶心死了
点赞 评论 收藏
分享
找工作勤劳小蜜蜂:自我描述部分太差,完全看不出想从事什么行业什么岗位,也看不出想在哪个地区发展,这样 会让HR很犹豫,从而把你简历否决掉。现在企业都很注重员工稳定性和专注性,特别对于热爱本行业的员工。 你实习的工作又太传统的it开发(老旧),这部分公司已经趋于被淘汰,新兴的互联网服务业,比如物流,电商,新传媒,游戏开发和传统的It开发有天然区别。不是说传统It开发不行,而是就业岗位太少,基本趋于饱和,很多老骨头还能坚持,不需要新血液。 工作区域(比如长三角,珠三角,成渝)等也是HR考虑的因素之一,也是要你有个坚定的决心。否则去几天,人跑了,HR会被用人单位骂死。
点赞 评论 收藏
分享
评论
1
3
分享

创作者周榜

更多
正在热议
更多
# 春招至今,你的战绩如何? #
8751次浏览 80人参与
# 你的实习产出是真实的还是包装的? #
1619次浏览 40人参与
# 巨人网络春招 #
11287次浏览 223人参与
# 军工所铁饭碗 vs 互联网高薪资,你会选谁 #
7337次浏览 40人参与
# 重来一次,我还会选择这个专业吗 #
433258次浏览 3926人参与
# 简历第一个项目做什么 #
31475次浏览 324人参与
# MiniMax求职进展汇总 #
23673次浏览 305人参与
# 当下环境,你会继续卷互联网,还是看其他行业机会 #
186809次浏览 1118人参与
# 不考虑薪资和职业,你最想做什么工作呢? #
152237次浏览 887人参与
# 研究所笔面经互助 #
118840次浏览 577人参与
# 简历中的项目经历要怎么写? #
309904次浏览 4183人参与
# 面试紧张时你会有什么表现? #
30466次浏览 188人参与
# 你今年的平均薪资是多少? #
212956次浏览 1039人参与
# AI时代,哪些岗位最容易被淘汰 #
63258次浏览 793人参与
# 我的求职精神状态 #
447945次浏览 3128人参与
# 你最满意的offer薪资是哪家公司? #
76388次浏览 374人参与
# 高学历就一定能找到好工作吗? #
64275次浏览 620人参与
# 牛客AI文生图 #
21395次浏览 238人参与
# 你怎么看待AI面试 #
179751次浏览 1224人参与
# 正在春招的你,也参与了去年秋招吗? #
363105次浏览 2635人参与
# 腾讯音乐求职进展汇总 #
160539次浏览 1109人参与
# 职能管理面试记录 #
10787次浏览 59人参与
牛客网
牛客网在线编程
牛客网题解
牛客企业服务