JDBC使用教程详解
文章目录
- 一、前言
- 二、JDBC概述
- 2.1 JDBC定义
- 2.2 JDBC接口调用方和实现方
- JDBC接口调用方
- JDBC接口实现方
- 2.3 连接数据库驱动
- 2.5 JDBC原理
- 三、JDBC编程url
- 3.1URL
- 3.3 SQL的分类
- 四、JDBC编程六步曲
- 4.1 第一步:注册驱动
- 4.2 第二步:获取数据库连接
- 4.3 第三步:获取数据库操作对象
- 4.4 第四步:执行SQL语句
- 4.5 第五步:处理查询结果集
- 4.6 第六步:释放资源
- 4.7 JDBC编程六步曲小结
- 五、Statement 和 PreparedStatement
- 6.1 SQL注入现象
- 6.1.1 SQL注入定义
- 6.1.2 SQL注入实例
- 6.1.3 如何解决SQL注入呢
- 6.2 Statement 和 PreparedStatement 对比
- 六、JDBC事务
- 6.1 事务的定义
- 6.2 事务的四个特性
- 6.3 JDBC中的事务
- 七、JDBC编程六步曲最终版
一、前言
项目开发中,操作数据库是必不可少的,常用的操作数据库的框架,如:MyBatis、JdbcTemplate等有很多。但是,无论使用哪种框架操作数据库,最底层的api实现都是JDBC,就是说,在开发中,JDBC有着举足轻重的地位,是最基础也是最核心的。
二、JDBC概述
2.1 JDBC定义
Java数据库连接,(Java Database Connectivity,简称JDBC)是Java语言中用来规范客户端程序如何来访问数据库的应用程序接口,提供了诸如查询和更新数据库中数据的方法。JDBC也是Sun Microsystems的商标。我们通常说的JDBC是面向关系型数据库的。
JDBC是Java语言连接数据库系统,JDBC接口是一套class文件,由SUN公司负责制定JDBC规范。
2.2 JDBC接口调用方和实现方
JDBC接口调用方
JDBC一般都是由程序员调用,用来连接数据库并且操作数据库。
JDBC接口实现方
数据库的厂商有很多,对应的数据库产品也很多,例如:MySQL、Oracle、DB2、SQLServer 等。各数据库厂商的程序员,负责编写SUN公司制定的JDBC接口的实现类。
2.3 连接数据库驱动
SUN公司负责制定JDBC规范,各数据库厂商编写的JDBC接口的实现类,编译之后将这些实现类打成 jar 包并且发布。
所有需要连接数据库的程序员,都需要从官网上下载这些jar再使用,这些专用驱动jar包通常被我们称为连接数据库的驱动。
2.5 JDBC原理
三、JDBC编程url
3.1URL
连接数据库时,需要使用URL连接,那么,什么是URL?
URl定义:
统一资源定位系统(uniform resource locator;URL)是因特网的万维网服务程序上用于指定信息位置的表示方法。它最初是由蒂姆·伯纳斯·李发明用来作为万维网的地址。现在它已经被万维网联盟编制为互联网标准RFC1738。(百度百科)
URL是统一资源定位符,代表网络中的某个资源的绝对路径
通过URL可以定位网络中的资源
URL主要包含四部分:协议、IP、端口号和资源名称
协议是: 提前制定好的通信数据格式、规范,按照这种特定格式发送数据包,对方收到数据包之后,也按照这种规范解析这个数据包,获取有价值数据
IP作用: 定位计算机
端口号作用: 定位服务
数据库中的URL:
如:MySQL和OracleMySQL数据库:jdbc:mysql://localhost:3366/databaseName
a、jdbc:mysql://表示协议
b、localhost表示IP
c、3366表示端口号
d、databaseName表示数据库名称
Oracle 数据库:jdbc:oracle:thin:@localhost:1521:databaseName
a、jdbc:oracle:thin:@表示协议
b、locahost表示IP
c、1521表示端口号
d、databaseName表示数据库名称
3.3 SQL的分类
数据库查询语言(DQL)
简称:DQL,Data Query Language
代表关键字:selectDQL主要是查询表中的数据数据库操作语言(DML)
简称:DML,Data Manipulation Language
代表关键字:insert、delete 、updateDML主要是增、删、改表中的数据数据库定义语言(DDL)
简称:DDL,Data Denifition Language
代表关键字:create、drop、alterDDL主要是创建、删除、修改表的结构事务控制语言(TCL)
简称:TCL,Trasactional Control Language
代表关键字:commit、rollbackTCL主要是对jdbc中的事务进行提交和回滚操作数据控制语言(DCL)
简称:DCL,Data Control Language
代表关键字:grant、revokeDML和DDL的区别是什么
DML是数据库操作语言,主要是修改数据库表中的数据,而DDL是数据库定义语言,主要修改数据中表的结构
四、JDBC编程六步曲
笔者以MySQL数据库为例
需要mysql驱动Maven依赖:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.15</version></dependency>
4.1 第一步:注册驱动
创建驱动对象,告知JDBC我们即将连接哪个数据库
通过DriverManager.registerDriver(driver)注册驱动
/*** <p>* 第一步:注册驱动* 通过创建驱动对象告知JDBC,我们即将连接哪个厂商的数据库* <p/>** @param* @return void* @Date 2020/6/7 11:23*/public static void registerDriver() {try {//注册驱动(new com.mysql.jdbc.Driver()也是可以的)Driver driver = new com.mysql.cj.jdbc.Driver();DriverManager.registerDriver(driver);} catch (SQLException e) {e.printStackTrace();}}
4.2 第二步:获取数据库连接
通过DriverManager.getConnection(url,user,pwd)获取连接
Connection连接对象不能随意创建,最后使用完要手动关闭
/*** <p>* 第二步:获取数据库连接* 注意:Connection连接对象不能随意创建,最后使用完需要手动关闭* <p/>** @param* @return java.sql.Connection* @Date 2020/6/7 11:24*/public static Connection getConnection() {try {//注册驱动registerDriver();//获取数据库连接//url统一资源定位String url = "jdbc:mysql://ip:3306/test";String userName = "zhangsan";String passWord = "zhangsan@";Connection connection = DriverManager.getConnection(url, userName, passWord);//打印Connection对象的内存地址:com.mysql.cj.jdbc.ConnectionImpl@69d9c55System.out.println("MySql数据库,对java.sql.Connection接口的实现类的完整类名:" + connection);return connection;} catch (SQLException e) {e.printStackTrace();}return null;}
MySQL数据库默认支持的最多连接数量为100
我们大家都知道MySQL最大连接数的默认值是100
,这个数值对于高并发下的应用是远远不够的,当连接请求大于默认连接数后,就会出现无法连接数据库的错误,因此我们需要把它适当调大一些。
在使用MySQL数据库的时候,经常会遇到这么一个问题,就是“Can not connect to MySQL server. Too many connections”-mysql 1040
错误,这是因为访问MySQL且还未释放的连接数目已经达到MySQL的上限。通常,mysql的最大连接数默认是100,最大可以达到16384。
MySQL查看最大连接数和修改最大连接数:
查看最大连接数
show variables like '%max_connections%'
;
修改最大连接数
set GLOBAL max_connections = 2000;
也可以通过修改配置文件来修改mysql最大连接数(max_connections),这种方式说来很简单,只要修改MySQL配置文件my.ini或my.cnf的参数max_connections,将其改为max_connections=2000
,然后重启MySQL即可。
4.3 第三步:获取数据库操作对象
一个数据库连接对象可以创建多个数据库操作对象
通过conn.createStatement()获取数据库操作对象
/*** <p>* 第三步:获取数据库操作对象* 拿到Statement数据库操作对象,就可以执行sql语句* <p/>** @param* @return java.sql.Statement* @Date 2020/6/7 11:42*/public static Statement getStatement() {try {//获取数据库连接Connection connection = getConnection();//获取数据库操作对象//一个连接对象,可以获取多个数据库操作对象Statement statementOne = connection.createStatement();//打印Statement对象的内存地址:com.mysql.cj.jdbc.StatementImpl@23f7d05dSystem.out.println("MySql数据库,对java.sql.Statement接口的实现类的完整类名:" + statementOne);//打印Statement对象的内存地址:com.mysql.cj.jdbc.StatementImpl@1e730495//Statement statementTwo = connection.createStatement();//System.out.println("MySql数据库,对java.sql.Statement接口的实现类的完整类名:" + statementTwo);return statementOne;} catch (SQLException e) {e.printStackTrace();}return null;}
4.4 第四步:执行SQL语句
通过数据库操作对象statement.executeUpdate(sql)
编译执行SQL
JDBC编写SQL语句不需要以分号结尾
数据库管理系统会将编写好的SQL语句编译并执行
【代码示例】
/*** <p>* 第四步:执行SQL语句* <p/>** @param* @return void* @Date 2020/6/7 11:51*/public static void executeSql() {try {//获取数据库操作对象Statement statement = getStatement();//执行SQL语句//注意:jdbc中,sql语句不需要以分好;结尾,当然,你写了也不会报错//定义DDL语句,这里可以创建表,但是,一般不这么玩,jdbc中,通常是写DML语句和DQL语句/*String sql = "CREATE TABLE `user` (\n" +" `id` bigint(32) NOT NULL auto_increment,\n" +" `userName` varchar(20) DEFAULT NULL COMMENT '用户名称',\n" +" `email` varchar(128) DEFAULT NULL COMMENT '邮箱|登录帐号',\n" +" `passWord` varchar(64) DEFAULT NULL COMMENT '密码',\n" +" `createTime` datetime DEFAULT NULL COMMENT '创建时间',\n" +" `lastLoginTime` datetime DEFAULT NULL COMMENT '最后登录时间',\n" +" `status` bigint(1) DEFAULT '1' COMMENT '1:有效,0:禁止登录',\n" +" PRIMARY KEY (`id`)\n" +") ENGINE=InnoDB DEFAULT CHARSET=utf8";*///定义DML语句String sql = StringUtils.join("insert into `user`(`userName`,`passWord`,`status`) values(", "'lisi','123','1')");//将sql语句发送给数据库管理系统,数据库管理系统(DBMS)会编译并执行该sql语句int count = statement.executeUpdate(sql);System.out.println(count);} catch (SQLException e) {e.printStackTrace();}}
4.5 第五步:处理查询结果集
处理查询结果集,获取当前光标指向行中的数据,有三种方式:
第一种方式:根据字段下标获取,不管数据库表中的字段是什么类型,都以字符串方式取出,JDBC所有下标都是以1开始
第二种方式:通过结果集中字段名称获取数据,该方式的程序更加健壮,建议使用
第三种方式:通过特定类型获取数据,该方式,明确知道字段的类型,可以节省类型转换花费的性能,该方式的程序更加健壮,性能更高,推荐使用
【代码示例】
/*** <p>* 第五步:处理查询结果集* <p/>** @param* @return void* @Date 2020/6/7 12:48*/public static void dealResultSet() {try {//获取数据库操作对象Statement statement = getStatement();//定义DQL语句String sql = StringUtils.join("select * from `user` where userName = 'lisi'");//将sql语句发送给数据库管理系统,数据库管理系统(DBMS)会编译并执行该sql语句,把查询结果集放到ResultSet结果集对象中ResultSet resultSet = statement.executeQuery(sql);//处理查询结果集,一个Statement可以得出多个ResultSet//resultSet.next()方法作用:if the new current row is valid, return true. if there are no more rows, return false//将光标向前移动一行,如果指向当前行有记录,则返回true,若指向当前行无记录,返回falsewhile (resultSet.next()) {//获取当前光标指向行中的数据,有三种方式://第一种方式:根据字段下标获取,不管数据库表中的字段是什么类型,都以字符串方式取出//JDBC所有下标都是以1开始String id1 = resultSet.getString(1);String userName1 = resultSet.getString(2);String status1 = resultSet.getString(7);System.out.println("id1:" + id1 + ",用户名1:" + userName1 + ",有效状态1:" + status1);//第二种方式:通过结果集中字段名称获取数据,该方式的程序更加健壮,建议使用String id2 = resultSet.getString("id");String userName2 = resultSet.getString("userName");String status2 = resultSet.getString("status");System.out.println("id2:" + id2 + ",用户名2:" + userName2 + ",有效状态2:" + status2);//第三种方式:通过特定类型获取数据,该方式,明确知道字段的类型,可以节省类型转换花费的性能,该方式的程序更加健壮,性能更高,推荐使用int id3 = resultSet.getInt("id");String userName3 = resultSet.getString("userName");String status3 = resultSet.getString("status");System.out.println("id3:" + id3 + ",用户名3:" + userName3 + ",有效状态3:" + status3);}} catch (SQLException e) {e.printStackTrace();}}
4.6 第六步:释放资源
一个Connection可以创建多个Statement,一个Statement可以得出多个ResultSet,所以先关闭ResultSet,再关闭Statement,最后关闭Connection
需要关闭ResultSet、Statement、Connection
为了保障能够释放资源,将释放代码编写到finally语句中
分别进行try catch关闭资源
JDBC驱动对象的创建、连接、获取数据库操作对象,执行sql、处理结果集等,都需要消耗时间,其中,这里面涉及到的ResultSet、Statement、Connection对象,使用完了需要释放,否则,造成资源浪费,严重的,服务器宕机
在编程时,由于用MySQL语句调用数据库时,在每次执行语句前,会做一个临时的变量用来打开数据库,所以你在使用MySQL语句的时候,记得在每次调用完MySQL之后就关闭MySQL临时变量。
【代码示例】
//释放资源部分代码片段catch (SQLException e){e.printStackTrace();} finally{//第六步:释放资源,分别进行try catch//从小的开始关闭try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (statement != null) {statement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}
4.7 JDBC编程六步曲小结
/*** <p>* JDBC编程六部曲* 第一步:注册驱动* 第二步:获取数据库连接* 第三步:获取数据库操作对象* 第四步:执行SQL语句* 第五步:处理查询结果集* 第六步:释放资源* <p/>** @param* @return void* @Date 2020/6/7 13:32*/public static void jdbcProgram() {//定义数据库连接对象Connection connection = null;//定义数据库操作对象Statement statement = null;//定义处理结果集对象ResultSet resultSet = null;try {//第一步:注册驱动,通过创建驱动对象告知JDBC,我们即将连接哪个厂商的数据库//注册驱动(new com.mysql.jdbc.Driver()也是可以的)Driver driver = new com.mysql.cj.jdbc.Driver();DriverManager.registerDriver(driver);//第二步:获取数据库连接//注意:Connection连接对象不能随意创建,最后使用完需要手动关闭//url统一资源定位String url = "jdbc:mysql://ip:3306/test";String userName = "zhangsan";String passWord = "zhangsan@";connection = DriverManager.getConnection(url, userName, passWord);//第三步:获取数据库操作对象//一个连接对象,可以创建多个数据库操作对象statement = connection.createStatement();//第四步:执行SQL语句//注意:jdbc中,sql语句不需要以分好`;`结尾,当然,你写了也不会报错//定义DQL语句,jdbc中,通常是写DML语句和DQL语句String sql = StringUtils.join("select * from `user` where userName = 'lisi'");//将sql语句发送给数据库管理系统,数据库管理系统(DBMS)会编译并执行该sql语句,把查询结果集放到ResultSet结果集对象中resultSet = statement.executeQuery(sql);//第五步:处理查询结果集//处理查询结果集,一个Statement可以得出多个ResultSet//resultSet.next()方法作用:if the new current row is valid, return true. if there are no more rows, return false//将光标向前移动一行,如果指向当前行有记录,则返回true,若指向当前行无记录,返回falsewhile (resultSet.next()) {//获取当前光标指向行中的数据(通过特定类型获取数据)//该方式,明确知道字段的类型,可以节省类型转换花费的性能,该方式的程序更加健壮,性能更高,推荐使用int id = resultSet.getInt("id");String name = resultSet.getString("userName");String status = resultSet.getString("status");System.out.println("id:" + id + ",用户名:" + name + ",有效状态:" + status);}} catch (SQLException e) {e.printStackTrace();} finally {//第六步:释放资源,分别进行try catch//从小的开始关闭try {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (statement != null) {statement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}
五、Statement 和 PreparedStatement
JDBC中,Statement 和 PreparedStatement这两个都是数据库操作对象,都可以操作sql获取到想要的结果,但是,这两个还是有一些差别。
6.1 SQL注入现象
6.1.1 SQL注入定义
定义
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
SQL是操作数据库数据的结构化查询语言,网页的应用数据和后台数据库中的数据进行交互时会采用SQL。而SQL注入是将Web页面的原URL、表单域或数据包输入的参数,修改拼接成SQL语句,传递给Web服务器,进而传给数据库服务器以执行数据库命令。如Web应用程序的开发人员对用户所输入的数据或cookie等内容不进行过滤或验证(即存在注入点)就直接传输给数据库,就可能导致拼接的SQL被执行,获取对数据库的信息以及提权,发生SQL注入攻击。
6.1.2 SQL注入实例
假设有一个场景: 用户通过进行用户名称,进行精确查询,用户输入的信息中有SQL关键字,并且参与了SQL语句的编译,导致SQL语句含义扭曲,最终导致了SQL注入。用户本来只应该查询到他自己的信息,但是却查出来了所有的用户信息。
SQL注入,简单来说,就是用一些SQL关键字,来导致一些不正常的现象,下面的这条sql,由于and优先级高于or,在用户录入userName = ‘lisi’ or ‘hello’ = 'hello’信息进行查询时,执行时sql就变成了select * from user where status = 1 and userName = ‘lisi’ or ‘hello’ = ‘hello’,导致SQL语句条件永远为真,会查出所有的用户信息数据。
select * from `user` where status = 1 and userName = {userName }
6.1.3 如何解决SQL注入呢
定义SQL语句框架的时候,使用PreparedStatement数据库操作对象,这个是预编译对象,先将SQL语句框架进行了编译,然后给参数?动态赋值。
先定义 SQL 语句构架,然后对SQL语句进行预先编译,select * from user where status = ? and userName = ?
ps = conn.prepareStatement(sql);
然后再接收用户提供的信息,即使用户提供的信息中包含SQL关键字,这些关键字也不参
与编译,是不起作用的。
主要修改的部分:
通过日志也可以看出,即使用户提供的信息中包含SQL关键字,这些关键字也不参
与编译,是不起作用的
预编译SQL:select * from user where status = ? and userName = ?
赋值后,编译的SQL: select * from user where status = ‘1’ and userName = ‘‘lisi’ or ‘hello’ = ‘hello’’,其实编译后的sql,是把用户录入的’lisi’ or ‘hello’ = ‘hello’,整体作为了一个字符串,即执行的sql是:select * from user where status = ‘1’ and userName = “‘lisi’ or ‘hello’ = ‘hello’”,这样就不会发生SQL注入问题了。
6.2 Statement 和 PreparedStatement 对比
PreparedStatement可以防止 SQL 注入,执行效率高
SQL语句对于Statement来说是:编译一次执行一次
SQL语句对于PreparedStatement来说,是编译一次执行N次
原因:数据库管理系统(DBMS)厂商实现了JDBC接口,DBMS将编译后的SQL语句保存在DBMS中,由于DBMS中有很多编译好的SQL语句,这时通过同一个PreparedStatement对象进行赋值,便会找到其对应的PreparedStatement对象,从而实现其参数的赋值,即:一次编译多次执行。
PreparedStatement是类型安全的,编译期可以检查传入参数类型
六、JDBC事务
6.1 事务的定义
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。(百度百科)
事务是恢复和并发控制的基本单位。
6.2 事务的四个特性
事务应该具有4个属性:原子性、一致性、隔离性、持久性,这四个属性通常称为ACID特性。
原子性(atomicity)
一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
一致性(consistency)
事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)
持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
6.3 JDBC中的事务
操作数据库时,肯定会有事务的存在,那么,JDBC中的事务是怎么使用的呢?
JDBC默认情况下,事务是自动提交的:即在JDBC中执行一条DML语句就执行了一次事务
将事务的自动提交,修改为手动提交即可避免自动提交
在事务执行的过程中,任何一步出现异常都要进行回滚
JDBC中使用事务只有三行代码:
设置手动提交事务:conn.setAutoCommit(false);
事务提交:conn.commit();
事务回滚:conn.rollback();
【代码示例】
在获取数据库连接后面开启事务,在 catch 语句块中进行事务回滚
七、JDBC编程六步曲最终版
/*** <p>* JDBC编程六部曲* 第一步:注册驱动* 第二步:获取数据库连接* 第三步:获取数据库操作对象* 第四步:执行SQL语句* 第五步:处理查询结果集* 第六步:释放资源* <p/>** @param* @return void* @Date 2020/6/7 15:50*/public static void jdbcProgramFinal() {//定义数据库连接对象Connection connection = null;//定义数据库操作对象PreparedStatement preparedStatement = null;//定义处理结果集对象ResultSet resultSet = null;try {//第一步:注册驱动,通过创建驱动对象告知JDBC,我们即将连接哪个厂商的数据库//注册驱动(new com.mysql.jdbc.Driver()也是可以的)/* Driver driver = new com.mysql.cj.jdbc.Driver();DriverManager.registerDriver(driver);*///第二步:获取数据库连接(这里面已经注册过驱动了,如果使用这种方式,上面就不用注册驱动了)//注意:Connection连接对象不能随意创建,最后使用完需要手动关闭//通过配置文件的方式(推荐使用)connection = getConnectionByConfiguration();//第三步:获取数据库操作对象(一个连接对象,可以创建多个数据库操作对象)if (connection == null) {System.out.println("获取数据库连接失败!");return;}//定义DQL语句,jdbc中,通常是写DML语句和DQL语句//定义SQL语句框架String sql = StringUtils.join("select * from `user` where status = ? and userName = ?");//执行到此,先将SQL语句框架进行了编译preparedStatement = connection.prepareStatement(sql);//这里假设是前台传的参数值String statusParam = "1";String userNameParam = "'lisi' or 'hello' = 'hello'";//给参数?动态赋值preparedStatement.setString(1, statusParam);preparedStatement.setString(2, userNameParam);//打印预编译SQL//System.out.println("预编译SQL:" + ((ClientPreparedStatement) preparedStatement).getPreparedSql());//打印赋值后,编译的SQL//System.out.println("赋值后,编译的SQL:" + ((ClientPreparedStatement) preparedStatement).asSql());//第四步:执行SQL语句//将sql语句发送给数据库管理系统,数据库管理系统(DBMS)会编译并执行该sql语句,把查询结果集放到ResultSet结果集对象中resultSet = preparedStatement.executeQuery();//第五步:处理查询结果集//处理查询结果集,一个Statement可以得出多个ResultSet//resultSet.next()方法作用:if the new current row is valid, return true. if there are no more rows, return false//将光标向前移动一行,如果指向当前行有记录,则返回true,若指向当前行无记录,返回falsewhile (resultSet.next()) {//获取当前光标指向行中的数据(通过特定类型获取数据),该方式,明确知道字段的类型,可以节省类型转换花费的性能,该方式的程序更加健壮,性能更高,推荐使用int id = resultSet.getInt("id");String name = resultSet.getString("userName");String status = resultSet.getString("status");System.out.println("id:" + id + ",用户名:" + name + ",有效状态:" + status);}} catch (SQLException e) {e.printStackTrace();} finally {//第六步:释放资源,从小的开始关闭,分别进行try catchtry {if (resultSet != null) {resultSet.close();}} catch (SQLException e) {e.printStackTrace();}try {if (preparedStatement != null) {preparedStatement.close();}} catch (SQLException e) {e.printStackTrace();}try {if (connection != null) {connection.close();}} catch (SQLException e) {e.printStackTrace();}}}/*** <p>* 通过配置文件的方式,获取数据库连接(推荐使用)* <p/>** @param* @return java.sql.Connection* @Date 2020/6/7 14:14*/public static Connection getConnectionByConfiguration() {try {//1.读取配置文件InputStream inputStream = JDBCTest003.class.getClassLoader().getResourceAsStream("db.properties");//2.创建属性对象Properties pro = new Properties();//3.通过属性对象的load()方法将配置文件读取到流中(Map集合对象中(内存中))pro.load(inputStream);//4.关闭流inputStream.close();//5.通过属性对象的getProperty(String key)方法获取配置文件中的value属性值String driver = pro.getProperty("db.driver");String url = pro.getProperty("db.url");String userName = pro.getProperty("db.username");String passWord = pro.getProperty("db.password");//注册驱动,这里必须是完整的类名(包名+类名)Class.forName(driver);//创建数据库连接Connection connection = DriverManager.getConnection(url, userName, passWord);return connection;} catch (IOException | ClassNotFoundException | SQLException e) {e.printStackTrace();}return null;}
JDBC使用教程详解相关推荐
- SAE上传web应用(包括使用数据库)教程详解及问题解惑
2019独角兽企业重金招聘Python工程师标准>>> 转自:http://blog.csdn.net/baiyuliang2013/article/details/24725995 ...
- linux卸载hadoop版本,centos6.5 安装hadoop1.2.1的教程详解【亲测版】
本篇只简单介绍安装步骤 1. 角色分配 10.11.84.4 web-crawler--1.novalocal master/slave 10.11.84.5 web-crawler--2.noval ...
- es springboot 不设置id_es(elasticsearch)整合SpringCloud(SpringBoot)搭建教程详解
注意:适用于springboot或者springcloud框架 1.首先下载相关文件 2.然后需要去启动相关的启动文件 3.导入相关jar包(如果有相关的依赖包不需要导入)以及配置配置文件,并且写一个 ...
- GitHub使用教程详解——官网操作指南(翻译)
GitHub使用教程详解--官网操作指南(翻译) GitHub使用指南 原文地址:GitHub官网 示例项目:Hello World 十分钟轻松教学 在学习计算机语言编程的过程中创建Hello Wor ...
- golang导入git包_使用go module导入本地包的方法教程详解
go module 是Go1.11版本之后官方推出的版本管理工具,并且从 Go1.13 版本开始, go module 将是Go语言默认的依赖管理工具.到今天 Go1.14 版本推出之后 Go mod ...
- Linux redis安装教程,Linux 下redis5.0.0安装教程详解
Linux redis5.0.0安装,教程如下所示: 1.从官网下载,然后传到服务器,tar -zxvf解压 2.进入redis ? 3.安装:make, (1)若提示:: gcc: Command ...
- windows上安装Anaconda和python的教程详解
一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...
- python安装教程windows-windows上安装Anaconda和python的教程详解
一提到数字图像处理编程,可能大多数人就会想到matlab,但matlab也有自身的缺点: 1.不开源,价格贵 2.软件容量大.一般3G以上,高版本甚至达5G以上. 3.只能做研究,不易转化成软件. 因 ...
- python3.8.1安装教程-Linux安装Python3.8.1的教程详解
本例以Linux上安装Pyhton3.8版本为例进行说明 1.依赖包安装 yum -y install zlib-devel bzip2-devel openssl-devel ncurses-dev ...
最新文章
- SAP RETAIL MM42维护商品采购信息记录数据的缺陷
- 通过 UDP 发送数据的简单范例
- 初学Java多线程【1】:线程简介
- springMVC图片的上传与下载
- 使用nodejs实现OData的batch操作在Marketing Cloud里读取contact信息
- MySQL主从延时这么长,要怎么优化?
- 挖槽!堪称神级的Java技术手册火了???(文末送书活动)
- python找数字程序_程序以查找Python中从1到N的所有缺失数字
- 一加9系列曝光:骁龙875旗舰芯片加持 可能存在超过四种机型
- LeetCode(455)——分发饼干(JavaScript)
- TabControl 切换 内嵌web页面直接响应滚动事件
- android水印图片素材,水印软件哪个好用app 安卓手机视频加图片水印的方法有吗?...
- Cubase Pro 12 v12.0.0 Full R2R WiN 音乐制作软件完整版
- 远行星号java 出错_远行星号跳出问题[已解决]
- 浅谈Unity中的rotation和Quaternion的乘法
- php 商户转账到微信零钱
- 电力电子技术(16)——直流斩波电路
- 笔记本桌面窗口管理器占用内存过高怎么办?
- 【数据结构】用Java实现动态数组
- 手游堡垒之夜服务器没响应,堡垒之夜国际服点启动没反应 | 手游网游页游攻略大全...
热门文章
- android 动画引擎,用 Android 实现一条小金鱼游动动画(超棒)
- 万兆网络传输速度测试_万兆带宽测试方法
- 【2013水王争霸赛】啊!
- 生活小妙招-通马桶(这是一篇有味道的博客~)
- pandas选取数据方法
- 打开掌柜宝怎么显示服务器繁忙,掌柜宝网关系统
- cad线性标注样式修改在哪里_自定义设置CAD标注样式教程
- 怎么更新opengl.dll文件_微信又更新了:群接龙怎么玩?文件如何备份?怎么发高清大视频?...
- checkstyle配置规格说明
- android将pdf文件转换成Bitmap,并将bitmap以图片的 方式保存到相册。