JDBC详细介绍

JDBC详细介绍目录前言 JDBC 介绍 JDBC 编程步骤 1 装载相应的数据库的 JDBC 驱动并进行初始化 2 建立 JDBC 和数据库之间的 Connection 连接 3 创建 Statement 或者 PreparedStat 接口 执行 SQL 语句 4 处理和显示结果 5 释放资源 Statement 和 PreparedStat 的异同及优缺点 execute 和 executeUpdat

目录

前言

JDBC介绍

JDBC编程步骤 

1.装载相应的数据库的JDBC驱动并进行初始化

2.建立JDBC和数据库之间的Connection连接

3.创建Statement或者PreparedStatement接口,执行SQL语句

4.处理和显示结果

5.释放资源

Statement和PreparedStatement的异同及优缺点

execute和executeUpdate的区别



前言

笔者花了一整天的时间仔细研究了JDBC的使用,内容很充实,代码也都经过了验证。如果你能够仔细阅读完这篇文章,JDBC的相关知识我想你一定会有所掌握。在阅读的过程中,有任何不理解的地方都欢迎留言讨论。

JDBC介绍

JDBC(Java DataBase Connectivity)是Java和数据库之间的一个桥梁,是一个规范而不是一个实现,能够执行SQL语句。它由一组用Java语言编写的类和接口组成。各种不同类型的数据库都有相应的实现,本文中的代码都是针对MySQL数据库实现的。

JDBC详细介绍

JDBC编程步骤 

1.装载相应数据库的JDBC驱动并进行初始化

  • 导入专用的jar包(不同的数据库需要的jar包不同)

        访问MySQL数据库需要用到第三方的类,这些第三方的类,都被压缩在一个.Jar的文件里。mysql-connector-java-5.0.8-bin.jar包可以在网上下载,或者在MySQL的安装目录下找到。通常下载到该jar包之后将其放到在项目的lib目录下,在本例就会放在E:\project\j2se\lib 这个位置,然后在eclipse中导入这个jar包。

        导包步骤: 右键project->property->java build path->libaries->add external jars

JDBC详细介绍

如果没有完成上述步骤的导包操作,后面会抛出ClassNotFoundException

  • 初始化驱动

      通过初始化驱动类com.mysql.jdbc.Driver,该类就在 mysql-connector-java-5.0.8-bin.jar中。如果你使用的是oracle数据库那么该驱动类将不同。

        注意:Class.forName需要捕获ClassNotFoundException.

try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); }

Class.forName是把这个类加载到JVM中,加载的时候,就会执行其中的静态初始化块,完成驱动的初始化的相关工作。 

2.建立JDBC和数据库之间的Connection连接

Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8", "root", "admin");

 Connection是与特定数据库连接回话的接口,使用的时候需要导包,而且必须在程序结束的时候将其关闭。getConnection方法也需要捕获SQLException异常。

因为在进行数据库的增删改查的时候都需要与数据库建立连接,所以可以在项目中将建立连接写成一个工具方法,用的时候直接调用即可:

 / * 取得数据库的连接 * @return 一个数据库的连接 */ public static Connection getConnection(){ Connection conn = null; try { //初始化驱动类com.mysql.jdbc.Driver Class.forName("com.mysql.jdbc.Driver"); conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/exam?characterEncoding=UTF-8","root", "admin"); //该类就在 mysql-connector-java-5.0.8-bin.jar中,如果忘记了第一个步骤的导包,就会抛出ClassNotFoundException } catch (ClassNotFoundException e) { e.printStackTrace(); }catch (SQLException e) { e.printStackTrace(); } return conn; }

3.创建Statement或者PreparedStatement接口,执行SQL语句

  • 使用Statement接口

Statement接口创建之后,可以执行SQL语句,完成对数据库的增删改查。其中 ,增删改只需要改变SQL语句的内容就能完成,然而查询略显复杂。在Statement中使用字符串拼接的方式,该方式存在句法复杂,容易犯错等缺点,具体在下文中的对比中介绍。所以Statement在实际过程中使用的非常的少,所以具体的放到PreparedStatement那里给出详细代码。

字符串拼接方式的SQL语句是非常繁琐的,中间有很多的单引号和双引号的混用,极易出错。

Statement s = conn.createStatement(); // 准备sql语句 // 注意: 字符串要用单引号' String sql = "insert into t_courses values(null,"+"'数学')"; //在statement中使用字符串拼接的方式,这种方式存在诸多问题 s.execute(sql); System.out.println("执行插入语句成功");
  • 使用PreparedStatement接口

与 Statement一样,PreparedStatement也是用来执行sql语句的与创建Statement不同的是,需要根据sql语句创建PreparedStatement。除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接。

给数据库中添加课程: (以下代码中最后关闭资源的两个方法 DbUtil.close(pstmt);  DbUtil.close(conn);  和上面的建立连接的方法是一样的,是在工具类中定义了的关闭方法,下文会给出其代码

 / * 添加课程 * @param courseName 课程名称 */ public void addCourse(String courseName){ String sql = "insert into t_course(course_name) values(?)"; //该语句为每个 IN 参数保留一个问号(“?”)作为占位符 Connection conn = null; //和数据库取得连接 PreparedStatement pstmt = null; //创建statement try{ conn = DbUtil.getConnection(); pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //给占位符赋值 pstmt.executeUpdate(); //执行 }catch(SQLException e){ e.printStackTrace(); } finally{ DbUtil.close(pstmt); DbUtil.close(conn); //必须关闭 } }

对数据库中的课程进行删除: 

 / * 删除课程 * @param courseId */ public void delCourse(int courseId){ String sql = "delete from t_course where course_id = ?"; Connection conn = null; PreparedStatement pstmt = null; try { conn = DbUtil.getConnection(); pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setInt(1, courseId); pstmt.executeUpdate(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ DbUtil.close(pstmt); DbUtil.close(conn); //必须关闭 } }

对数据库中的课程进行修改:

 / * 修改课程 * @param courseId * @param courseName */ public void modifyCourse(int courseId,String courseName){ String sql = "update t_course set course_name =? where course_id=?"; Connection conn = null; PreparedStatement pstmt = null; try { conn = DbUtil.getConnection(); pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值 pstmt.setInt(2, courseId); pstmt.executeUpdate(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ DbUtil.close(pstmt); DbUtil.close(conn); //必须关闭 } }

 由上面的增删改程序可以看出,他们的代码都是大同小异的,主要是SQL语句存在差异,其他的地方几乎是完全相同的。其中有几个地方需要注意:

  1. 使用PreparedStatement时,他的SQL语句不再采用字符串拼接的方式,而是采用占位符的方式。“?”在这里就起到占位符的作用。这种方式除了避免了statement拼接字符串的繁琐之外,还能够提高性能。每次SQL语句都是一样的,java类就不会再次编译,这样能够显著提高性能。后面需要用到PreparedStatement接口创建的pstmt的set方法给占位符进行赋值。注意一点,这里的参数索引是从1开始的。
    String sql = "update t_course set course_name =? where course_id=?";
    pstmt = (PreparedStatement) conn.prepareStatement(sql); pstmt.setString(1, courseName); //利用Preparedstatement的set方法给占位符赋值 pstmt.setInt(2, courseId); pstmt.executeUpdate();

    增删改都使用pstmt.executeUpdate();语句进行SQL语句的提交 ,下文的查询会有所不同,请注意。

  2. 在添加的过程的,如果添加的数据量比较大的话,可以用批量添加。  PreparedStatement接口提供了相应的批量操作的方法。
for(int i=1;i<100;i++){ pstmt.setInt(1,8000+i); pstmt.setString(2,"赵_"+i); pstmt.addBatch(); //批量更新 if(i%10==0){ pstmt.executeBatch(); } }

下面我们来看稍显麻烦一点的查询操作:

 / * 查询课程 * @return */ public List 
    
      findCourseList(){ String sql = "select * from t_course order by course_id"; Connection conn = null; PreparedStatement pstmt = null; ResultSet rs = null; //创建一个集合对象用来存放查询到的数据 List 
     
       courseList = new ArrayList<>(); try { conn = DbUtil.getConnection(); pstmt = (PreparedStatement) conn.prepareStatement(sql); rs = (ResultSet) pstmt.executeQuery(); while (rs.next()){ int courseId = rs.getInt("course_id"); String courseName = rs.getString("course_name"); //每个记录对应一个对象 Course course = new Course(); course.setCourseId(courseId); course.setCourseName(courseName); //将对象放到集合中 courseList.add(course); } } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); }finally{ DbUtil.close(pstmt); DbUtil.close(conn); //必须关闭 } return courseList; } 
      
    

查询操作使用executeQuery()进行更新。其他相关的问题放在第四步(处理和显示结果)中解释。

4.处理和显示结果

 执行查询语句,并把结果集返回给集合ResultSet

ResultSet rs = s.executeQuery(sql);

利用While(ResultSet.next()){
…}循环将集合ResultSet中的结果遍历出来。

ResultSet.getXX();     这里的get方法的括号里面可以填属性值,如下图代码中的course_id,还可以填该属性在数据表中的列号,从1开始编码,例如:course_id在我的t-courses数据表中位于第一列,所以执行get方法的时候,我除了代码段中写法外,还可以这样写int courseId = rs.getInt(1);但是不推荐使用列号的这种方式,因为一段数据表中个属性值得顺序发生变化,就会导致这里出错,而使用属性名则不会出现这样的问题。

while (rs.next()){ int courseId = rs.getInt("course_id"); String courseName = rs.getString("course_name"); //每个记录对应一个对象 Course course = new Course(); //在我的项目中创建了course类,其中定义了set方法,所以这里将查询到的值传给了course,也可以直接打印到控制台 course.setCourseId(courseId); course.setCourseName(courseName); //将对象放到集合中 courseList.add(course); }

还有一点需要说明的是:

        因为在我的项目中创建了course类,其中定义了set方法,所以这里将查询到的值传给了course,你也可以直接用打印语句将CourseId和CourseName打印到控制台。

 course.setCourseId(courseId);  course.setCourseName(courseName); 

5.释放资源

在JDBC编码的过程中我们创建了Connection、ResultSet等资源,这些资源在使用完毕之后是一定要进行关闭的。关闭的过程中遵循从里到外的原则。因为在增删改查的操作中都要用到这样的关闭操作,为了使代码简单,增加其复用性,这里我将这些关闭的操作写成一个方法和建立连接的方法一起放到一份工具类中。

/ * 封装三个关闭方法 * @param pstmt */ public static void close(PreparedStatement pstmt){ if(pstmt != null){ //避免出现空指针异常 try{ pstmt.close(); }catch(SQLException e){ e.printStackTrace(); } } } public static void close(Connection conn){ if(conn != null){ try { conn.close(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } } } public static void close(ResultSet rs){ if (rs != null) { try { rs.close(); } catch (SQLException e) { // TODO: handle exception e.printStackTrace(); } } }

 JDBC编程的内容就这些了,如果你已经全部掌握,还有事务、获取自增、获取元数据、ORM、DAO、数据连接池等内容可以自行了解一下。

另外,Statement和PreparedStatement的异同,execute和executeUpdate的区别等内容,这里做一些介绍。

Statement和PreparedStatement的异同及优缺点

同:两者都是用来执SQL语句的

异:PreparedStatement需要根据SQL语句来创建,它能够通过设置参数,指定相应的值,不是像Statement那样使用字符串拼接的方式。

PreparedStatement的优点:

1、其使用参数设置,可读性好,不易记错。在statement中使用字符串拼接,可读性和维护性比较差。

2、其具有预编译机制,性能比statement更快。

3、其能够有效防止SQL注入攻击。

execute和executeUpdate的区别

相同点:二者都能够执行增加、删除、修改等操作。

不同点:

1、execute可以执行查询语句,然后通过getResult把结果取出来。executeUpdate不能执行查询语句。

2、execute返回Boolean类型,true表示执行的是查询语句,false表示执行的insert、delete、update等。executeUpdate的返回值是int,表示有多少条数据受到了影响。

 

关于JDBC的介绍就这么多了,欢迎评论区讨论。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211963.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午9:10
下一篇 2026年3月18日 下午9:10


相关推荐

  • docker复制文件到宿主机_下面哪几个属于docker网络模式

    docker复制文件到宿主机_下面哪几个属于docker网络模式自从Docker容器出现以来,容器的网络通信就一直是被关注的焦点,也是生产环境的迫切需求。容器的网络通信又可以分为两大方面:单主机容器上的相互通信,和跨主机的容器相互通信。 一、端口映射(局域网,外网此方式均可)。此种方式是将容器的某个端口映射到宿主机的某个端口,其它主机访问容器提供的服务需要通过宿主机的IP进行访问:dockerrun-p9000:8000–namec…

    2022年8月21日
    11
  • RC电路(积分电路,微分电路)

    RC电路(积分电路,微分电路)RC 电路是电阻器电容器电路 RC 电路 或者 RC 过滤器 RC 网络是电路 a 和电容器驾驶的组成由电阻器电压或当前来源 一次 RC 电路由一个电阻器和一台电容器组成 是 RC 电路的简单例子 RC 电路在模拟电路 脉冲数字电路中得到广泛的应用 目录 RC 电路的分类 RC 电路的典型应用 RC 实用电路 RC 电路的分类 1 RC 串联电路 电路的特点 由于有电

    2026年3月26日
    2
  • Android Linux内核编译

    Android Linux内核编译

    2021年9月3日
    63
  • LinkedHashMap实现原理

    LinkedHashMap实现原理1 LinkedHashMa 概述 nbsp nbsp nbsp nbsp nbsp LinkedHashMa 是 Map 接口的哈希表和链接列表实现 具有可预知的迭代顺序 此实现提供所有可选的映射操作 并允许使用 null 值和 null 键 此类不保证映射的顺序 特别是它不保证该顺序恒久不变 nbsp nbsp nbsp nbsp nbsp LinkedHashMa 实现与 HashMap 的不同之处在于 后者维护着一个运行于所有条目的双重链接列表 此链接列表定义了迭代顺序

    2025年9月26日
    5
  • 计算机命令netstat,电脑netstat命令的使用方法

    计算机命令netstat,电脑netstat命令的使用方法netstat 命令有什么作用 netstat 一般用于显示与 IP TCP UDP 和 ICMP 协议相关的统计数据 一般用于检测本机各端口的网络连接情况 接下去和大家分享一下 windows 电脑 netstat 命令的使用方法 具体方法如下 1 首先我们介绍第一条命令用法 执行命令 netstat a 显示所有连接和监听端口 LISTEN 在监听状态中 ESTABLISHED 已建立连

    2026年3月18日
    2
  • StackOverflowError 异常原因

    StackOverflowError 异常原因StackOverflo 之前仅知道递归方法容易出现该异常 但是我的开发代码中并没有使用到递归或者死循环 后面发现是由于两个类相互实例化导致的栈溢出 其实这种写法本身就是高度耦合的低级错误行为

    2026年3月19日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号