失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > JDBC连接数据库 --- JDBC编程6步【Java】

JDBC连接数据库 --- JDBC编程6步【Java】

时间:2019-05-16 07:41:06

相关推荐

JDBC连接数据库 --- JDBC编程6步【Java】

JDBC初步学习笔记

内容导航

JDBC java database connectivityJDBC介绍JDBC环境配置JDBC编程6步注册驱动获取数据库连接获取数据库操作对象执行SQL语句 execute处理查询结果集资源释放编程实现

Java养成计划77天


jdbc连接数据库


现在先将表面的知识学习完成之后,才会进一步来深入学习,比如计组,JDK源码,计网,数据库原理;现在的初期目标是能够熟练操作java相关,初步完成一个完整简单的项目;包括数据库表,java编程;涉猎一下web编程;全栈操作,重在后端

昨天已经完成数据库表的学习,包括索引和视图,当然非常浅显,但是目的是为了拓宽知识面,先能够熟练的运用,运用熟练之后学习底层应该会容易一些

JDBC java database connectivity

学习数据库的目的就是为了更好的管理数据,管理数据的目的是为了让应用得到更好的实现,那么既已经初步学习了数据库,接下来就应该是考虑数据库如何在程序中使用,java中要使用数据库,就离不开JDBC,那么什么是JDBC呢?

JDBC介绍

想到jdbc,就会想到很多缩略词比如CRUD,ACID,这些都是对应的英语单词取首字母形成的,这里的JDBC就是java dababase connectivity java数据库连接工具 ;

JDBC本质 : 是SUN公司制定的一套接口【interface】 接口按照之前的知识分为调用者和实现者;面向接口调用、面向接口写实现类;适配器,抽象类;

面向接口编程的目的 :解耦合,提高程序的可扩展性主要是理解什么是耦合,耦合就是模块间的关联程度,关联程度越高,那么耦合度越高;比如new 对象的时候,对象不存在,编译出错,无法运行,这个时候就是耦合度提高的;还有比如实现图书的格式多种html,xml之类;设计的时候不能放在一个类中,这样修改的时候会很麻烦,耦合度太高,实际上各种格式之间的耦合度应该很低,这个时候就使用strategy pattern,面向接口编程来降低耦合,俗称解耦

面向具体编程,会导致程序过僵,耦合度太高,扩展性很低 【所以面向接口编程】

SUN指定了一套JDBC接口,这时因为每一个数据库的地城实现原理都不一样,Oracle,MySQL等各个数据库的底层原理都不一样,每一个数据库产品都有自己独特的实现原理 -------- 各个数据库厂家都去实现JDBC接口的实现类,就是一套.class文件;

而Programmer就是面向JDBC一套接口,我们可以进入JAVA 的帮助文档中,可以发现一java.sql包中的接口就有一个connection接口,这个接口就是连接数据库的超级接口,各个数据库都对其进行了实现

而MySQL对其的实现就是可以看到几个.class文件,包括Driver.class;SocketFactory.class,SocketFactorWrapper.class等Java文件; 各个数据库对于jdbc的实现称为驱动driver,比如我下载的就是MySQL驱动

驱动: 所有的数据库的驱动都是以jar包的形式存在,jar包中有很多.class文件,这些.class文件就是对JDBC接口的实现

驱动不是SUN公司提供,而是各个数据库厂家去下载jar包才可以

关于数据库的模拟可以看一下之前的博客,之前分享反射的时候就是以数据库迁移来分享的,这里使用了配置文件properties文件,创建文件,利用class类的forname方法获取类的对象,之后创建实例,利用newInstance方法创建对象,这里使用上转型就可以了,上转型可以强转或者不转;下转型使用instanceof判断之后再强制类型转换;

当然除了Properties类,也可以使用ResourceBundle 绑定类来获取文件中的数据

JDBC环境配置

jdbc的.class文件都是从网上下载的,这些文件没有在java bin中,所以需要配置classpath变量

classpath没有配置文件的情况下,默认从当前路径下加载class,calsspath如果配置死了,比如 classpath = D:\abc ,则表示只从abc下找class;但是我们自己写的class也要进行类加载,之前运行java程序的时候就是在当前路径下,因为指明了.java文件,路径明了;

那么路径就要配置为.😄:\…… .代表的当前路径下 ;代表的是该变量的另外一种值

jar包不需要解压,类加载器可以自动找到文件

JDBC编程6步

注册驱动 : 通知java程序即将连接那种数据库获取数据库连接 : java和mysql进程之间的连接通道开启了获取数据库操作对象 :数据库操作对象可以执行SQL语句执行SQL语句 : 执行CRUD语句处理查询结果集 : 如果第四步是SELECT语句,才有第五步释放资源 : jdbc是进程之间的通信,需要关闭以减少资源的耗费

注册驱动

驱动在数据库方面就是Driver,那么注册驱动就是告诉Java程序需要连接的是哪个品牌的数据库;

上面提到SUN公司提供了一套接口JDBC,当然就有接口和相关的类负责驱动注册了

在java程序中,分管sql的是java.sql包,该包中有一个类为Driver

Driver : 每一各驱动程序都必须要实现的接口,java SQL允许多种数据库,DriverManager会试着尽可能多加载可以找到的驱动程序,依次尝试连接URL : 简单一点,这个接口就是为了方便导入各种不同的数据库驱动 com.mysql.jdbc.Driver是mysql数据库实现Driver接口DriverManager :驱动的注册使用到java.sql包中的DriverManager类 : 该类的作用就是管理一组JDBC驱动,应用程序不再需要使用 Class.forName() 显式地加载 JDBC 驱动程序。当前使用 Class.forName() 加载 JDBC 驱动程序的现有程序将在不作修改的情况下继续工作

需要注意的是加载驱动不是在com.mysql.jdbc.Driver下了,而是在com.mysql.cj.jdbc.Driver,还要注意修改时间

java中因为各个数据库公司实现了SUN公司提供的接口,但是名称是一样的,这个时候就不能两边都省略了,因为JVM是识别不了到底谁是谁,这个时候一个导入import,另外一个直接加上包名就可以不用导入了

一般注册驱动就两步

创建一个具体的Driver对象利用DriverManager的类方法registerDriver 注册给定的驱动 ,利用Manager管理 【会抛出SQLException,因为数据库可能连接失败】

Driver driver = new com.mysql.jdbc.Driver();//Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.DriverManager.registerDriver(driver);

获取数据库连接

上面第一步注册驱动只是引入Mysql驱动程序 ---- 可以允许mysql数据库了,但是还没有获取到mysql中的数据库,那么接下来还是要使用DriverManager中的类方法getConnections ---- 都会抛SQLException,这种方法重载了,因为可以使用配置文件来书写密码和用户,还可以直接写密码和用户【String】 String – URL

建立到给定数据库URL(uniform resource locator统一资源定位符)的连接,DriverManager则从已经注册的驱动程序中选择一个合适的【因为是一组不是一个】

getConnections(String url,String user, String password) throws SQLException 【返回的Connection对象】 Connection接口和Driver接口一样都是sql包下的,Connection表示的是java程序和数据库之间的连接关系【之前说过可以使用singleton pattern】

这里的user和password就是用户和密码,和mysql中的-u -p 相同,都是String类型的就可

要注意数据库的url的写法:

url之前在计网中介绍过,就不再介绍了,url包括 协议 ip 端口 路径 用户etc protocol分层,垂直service

jdbc:mysql:// 这是java和mysql通信的协议就类似htttps://localhost 本机ip地址 127.0.0.1端口号 3306cfengtest 数据库名称?serverTimezone=GMT%2B8 时间【低版本可以不加】

Oracle : oracle:jdbc:thin:@localhost:3306:cfengtest

String user = "cfeng";String password = "*********";String url = "jdbc:mysql://localhost:3306/cfengtest?serverTimezone=GMT%2B8";Connection conn = DriverManager.getConnection(url, user, password);//取得一个数据库连接对象System.out.println(conn);//com.mysql.cj.jdbc.ConnectionImpl@f0c8a99 这里其实可以看出来就是创建一个mysql的连接对象;当然不同的数据库是不同的对象 都是实现的sun的接口Connection

获取数据库操作对象

上面第二步已经获取到了数据库连接对象了,那么要想操作数据库中的数据,必须要有数据库操作对象,数据库操作对象的获取可以使用==Connection接口中的createStatement()方法

该方法可以创建一个statement对象来讲SQL语句发送到数据库

连接对象只是管连接的,可以操作连接状态;Statement【也是sun的一个总接口】对象是在连接的基础上传送语句的

通过一个连接对象Connection是可以创建多个Statement对象的

Statement state = conn.createStatement(); //这里就简单获取一个对象就可以了System.out.println(state);//com.mysql.cj.jdbc.StatementImpl@7674f035

执行SQL语句 execute

【execute 执行】

这里要使用Statement中的方法就可以了,比如executeUpdate 语句就是DML语句都可,可以返回int型的修改了多少rows的记录

excute(String sql) sql语句也是String类型的

String sql = "INSERT INTO emp (empno,ename) VALUES (15,'ROBIT')";int count = state.executeUpdate(sql);System.out.println(count);//1代表影响了数据库中的一行记录,可以去数据库中看一下效果mysql> SELECT * FROM emp;+-------+--------+-----------+------+------------+---------+---------+--------+| empno | ename | job | mgr | hiredate | sal| comm | deptno |+-------+--------+-----------+------+------------+---------+---------+--------+| 15 | ROBIT | NULL| NULL | NULL | NULL | NULL | NULL || 7369 | SMITH | CLERK| 7902 | 1980-12-17 | 800.00 | NULL |20 || 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600.00 | 300.00 |30 || 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250.00 | 500.00 |30 || 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975.00 | NULL |20 || 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250.00 | 1400.00 |30 || 7698 | BLANK | MANAGER | 7839 | 1981-05-01 | 2850.00 | NULL |30 || 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450.00 | NULL |10 || 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000.00 | NULL |20 || 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000.00 | NULL |10 || 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500.00 | 0.00 |30 || 7876 | ADAMS | CLERK| 7788 | 1987-05-23 | 1100.00 | NULL |20 || 7900 | JAMES | CLERK| 7698 | 1981-12-03 | 950.00 | NULL |30 || 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000.00 | NULL |20 || 7934 | MILIER | CLERK| 7782 | 1982-01-23 | 1300.00 | NULL |10 |+-------+--------+-----------+------+------------+---------+---------+--------+

可以看到是成功插入了数据的🌳

再来多实验几次,DELETE语句和UPDATE语句

String sql = "UPDATE emp SET ename = 'Cfeng' WHERE empno = 15";int count = state.executeUpdate(sql);System.out.println(count);//1mysql> SELECT * FROM emp;+-------+--------+-----------+------+------------+---------+---------+--------+| empno | ename | job | mgr | hiredate | sal| comm | deptno |+-------+--------+-----------+------+------------+---------+---------+--------+| 15 | Cfeng | NULL| NULL | NULL | NULL | NULL | NULL

再来看一下DELETE

String sql = "DELETE FROM emp WHERE empno = 15";int count = state.executeUpdate(sql);System.out.println(count);//1mysql> SELECT * FROM emp;| 7934 | MILIER | CLERK| 7782 | 1982-01-23 | 1300.00 | NULL |10 |+-------+--------+-----------+------+------------+---------+---------+--------+14 rows in set (0.01 sec)

可以看到和之前单独使用dos窗口操作时一样的效果,只是要注意SQL语句的正确性

处理查询结果集

当上面的SQL语句为DQL的时候,这个时候就要调用数据库操作对象的executeQuery()方法,这个方法返回的是一个ResultSet对象

ResultSet是一个接口,超级接口为Wrapper,表示的是数据库结果集的数据表ResultSet对象有一个光标指向当前数据行,最初光标放置在第一行前面,next方法可以将其移动到下一行,如果没有下一行返回false,所以可以用while迭代结果集ResultSet对象也需要释放,不然会占用资源,但是释放不会关闭创建的blob或者clob对象,需要使用free才会消失这个对象中存储了查询出的数据,所以要看到数据就是对ResultSet的操作,可以遍历输出,遍历操作,取出数据get光标指向的是第一行的数据,next移动就是指向的是每一row;----这里就通过这个光标取出该row的第一个数据JDBC中所有的下标都是从1开始的,通过getString(columindex)方法取得第index位置的数据【不管是什么类型都是以String类型返回

rset = state.executeQuery(sql);while(rset.next()) {String emp = rset.getString(1) + " " + rset.getString(2) + " " + rset.getString(3);//上面的SQL语句查询的每一行的记录是3col,所以从1到3System.out.println(emp);}

上面是取出的都是String类型的,其实也可以用特定类型的,比如getInt,getDouble ……除了根据columindex查询,还可以根据名称查询,注意 : 这里的名称不是表中字段的名字,而是查询结果的名称,如果起别名了就不是了,因为存储的是查询结果那张表的数据,直接getString(“col_name”)字段下标不健壮,因为一旦修改之后,位置可能变化,但是字段名称很少变化

资源释放

因为维护进程通信连接是需要资源的,还有statement也需要维护,所以要释放掉资源不用的时候

这里的释放因为上面的try catch,所以直接在finally中释放,关于finally的考点比如return,exit之类的就不再赘述,因为try形成了语句块,又变量的作用域和生命周期,所以这里变量声明放在try的外面,方便在finnally中释放

那或许会疑惑: 放在里面不是更省事吗?这样就不用再写try catch了

这个问题主要是应对一些其他的情况,finally除了强制关闭jvm都是可以执行的,所以放在finally中或许更好一些

//先关闭ResultSet,关闭state,再关闭connectionif(state != null) {state.close();}if(conn != null) {conn.close();}//放在finally中要分别try catch

编程实现

这里已经知道编程6步,那么就要实践一下,看一下如何运用

package test;import java.sql.*;public class JdbcTest {public static void main(String[] args) {//注册驱动Connection conn = null;Statement state = null;ResultSet rset = null;try {DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());//获取数据库连接对象String url = "jdbc:mysql://localhost:3306/cfengtest?servertimezone=GMT%2B8";String user = "cfeng";String password = "************";conn = DriverManager.getConnection(url, user, password);//获取数据库操作对象state = conn.createStatement();//直接再连接的基础上来创建对象//执行SQL语句String sql = "SELECT empno,ename,sal FROM emp LIMIT 5";rset = state.executeQuery(sql);while(rset.next()) {String emp = rset.getString(1) + " " + rset.getString(2) + " " + rset.getString(3);//上面的SQL语句查询的每一行的记录是3col,所以从1到3System.out.println(emp);}//获取数据库查询结果集} catch (SQLException e) {e.printStackTrace();}finally {//释放资源if(rset != null) {try {rset.close();} catch (SQLException e) {e.printStackTrace();}if(state != null) {try {state.close();} catch (SQLException e) {e.printStackTrace();}if(conn != null) {try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}}}}}//建议获取数据使用名称,比下标健壮/*7369 SMITH 800.07499 ALLEN 1600.07521 WARD 1250.07566 JONES 2975.07654 MARTIN 1250.0*/

如果觉得《JDBC连接数据库 --- JDBC编程6步【Java】》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。