【Java学习笔记】 MYSQL03 学习使用JDBC访问数据 以及 JDBC的优化和封装
通过JDBC 访问数据
学习时间 7月11日
一、使用Java访问数据库
JAVA 主动 提出接口 ,各种数据库适应 这些接口
- 接口就是 JDBC Java Database Connector
- 各种数据库都会提供一套对应的驱动程序(JAR文件
- 即不同的数据库都有自己对应的JAR文件
1、导入mysql对应的JAR包
- 创建lib文件夹
- 将jar文件放入
- 右键jar包,点击
add as library
导入包
2、访问数据库的步骤
加载驱动:涉及到反射
Class.forName
需要捕获异常- 快速添加异常的快捷键
Alt + 回车
,选第二个
- 快速添加异常的快捷键
连接数据库:查找db文件
配置url :
jdbc:mysql://127.0.0.1:3306/zy_sys?useUnicode=true&characterEncoding=UTF-8&useSSL=false
ip地址,数据库名字,编码unicode,不使用加密
zy_sys
对应的是数据库名称
创建连接 :
Connection connection = DriverManager.getConnection(url , user , password);
- 也需要异常捕获
写SQL语句
- 创建一个字符串存储 SQL语句
- 建议先在DBMS中测试一次
预编译SQL语句(判断语法错误,获取执行的对象)
- 固定语法:
PreparedStatement preparedStatement = connection.prepareStatement(sql);
- 固定语法:
执行操作
获取执行结果
增删改调用方法
executeUpdate()
:- 返回类型int 表示受影响的条数
- 获取执行结果只需要输出这个返回值即可
查找调用方法
executeQuery()
:返回值类型是
ResultSet
(结果集:类似对象列表)用 while 循环 遍历结果集.
用到
ResultSet.next()
方法——向下移动一行,返回布尔值。默认是在空行,next一行才是第一行。举个例子如下:while (resultSet.next()){// 使用对应的方法获得相应的数据类型String sno = resultSet.getString("sno");String sname = resultSet.getString("sname");int sage = resultSet.getInt("sage");// 按顺序输出结果即可System.out.println(sno + "\t" + sname + " \t" + sage);}
关闭操作(关闭连接,关闭接口,关闭对象) 释放资源
- 关闭顺序有大小之分,小的先关,大的后关
3、举个例子(增删改
package com.cykj.demo;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class Test {public static void main(String[] args) {try {// 1、加载驱动 ——涉及到反射知识点Class.forName("com.mysql.jdbc.Driver"); // Driver类 驱动String url = "jdbc:mysql://127.0.0.1:3306/zy_sys?useUnicode=true&characterEncoding=UTF-8&useSSL=false";// 2、连接数据库String user = "root"; // 账号String password = "root"; // 密码Connection connection = DriverManager.getConnection(url , user , password); // 创建连接System.out.println("连接成功!");// 3、写SQL语句String sql = "INSERT INTO zy_student(sno,sname,ssex) VALUES ('jx220501','老王',1)";// 4、预编译PreparedStatement preparedStatement = connection.prepareStatement(sql);// 5、执行操作int re = preparedStatement.executeUpdate();// sql的增删改都用executeUpdate() 返回类型int 表示受影响的条数// 6、获取执行结果System.out.println(re);// 7、关闭preparedStatement.close(); // 关闭编译connection.close(); // 关闭连接// 关闭顺序有大小之分,小的先关,大的后关} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}
}
4、 查找例子
package com.cykj.demo;import java.sql.*;public class Test2 {public static void main(String[] args) {try {// 1、加载驱动 ——涉及到反射知识点Class.forName("com.mysql.jdbc.Driver"); // Driver类 驱动// 2、连接数据库String url = "jdbc:mysql://127.0.0.1:3306/zy_sys?useUnicode=true&characterEncoding=UTF-8&useSSL=false";String user = "root"; // 账号String password = "root"; // 密码Connection connection = DriverManager.getConnection(url , user , password); // 创建连接System.out.println("连接成功!");// 3、写SQL语句String sql = "SELECT sno,sname,sage FROM zy_student WHERE sno LIKE 'AF%';";// 4、预编译PreparedStatement preparedStatement = connection.prepareStatement(sql);// 5、执行操作ResultSet resultSet = preparedStatement.executeQuery(); // 查找数据库用的是executeQuery()// 6、获取执行结果while (resultSet.next()){// 使用对应的方法获得相应的数据类型String sno = resultSet.getString("sno"); String sname = resultSet.getString("sname");int sage = resultSet.getInt("sage");// 按顺序输出结果即可System.out.println(sno + "\t" + sname + " \t" + sage);}// 7、关闭resultSet.close();preparedStatement.close(); // 关闭编译connection.close(); // 关闭连接// 关闭顺序有大小之分,小的先关,大的后关} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}}
}===输出结果===
AF121101 小王 22
AF121102 小红 22
AF121103 王思思 23
AF121104 小灰 30
AF121105 小林 27
AF121106 小张 26
AF121107 小丽 32
AF121108 小花 29
AF121109 小马 26
JDBC优化
一、在预编译时拼接字符串
SQL语句的拼接,有什么缺点?
- 写法麻烦
- 不安全,留有SQL注入的风险
如何解决呢?
用问号?替代字符串中需要拼接的位置
- 在预编译时加入字符串,举个例子
// 原字符串 String sql = "SELECT * FROM tb_user WHERE userid = '" + useridText + "' OR username = '" + useridText + "'";
- 修改后
// 用问号替代拼接的字符串 意思类似挖坑 String sql = "SELECT * FROM tb_user WHERE userid = ? OR username = ?";; ps = connection.prepareStatement(sql); // 预编译 // 利用setString()方法 插入字符串,计数从1开始 ps.setString(1,useridText); ps.setString(2,useridText);
- 简单理解:这种方法类似挖坑和填坑
- 先挖坑:用问号?替代也要拼接的字符串
- 再填坑,利用setString()方法 插入字符串,计数从1开始
- 注意:setString会自动给这个字符串加入单引号,无需再添加
二、优化关闭操作
在JDBC操作中,如果编译出现报错,后续的关闭操作就不再执行了。这样会导致数据库负担较大
- 要如何解决该问题呢?
- 利用异常关键字finally的特点:异常处理中finally是最后必须执行一次的,可以把关闭操作写在这里!
- 要如何解决该问题呢?
具体操作如下
将需要关闭的对象,设置为全局变量
目标**:在finally语句块里关闭对象**
关闭时也要加入异常捕获,注意:每次关闭都要分别捕获异常
在关闭前,也要加入一个if判断,判断对象不等于null,才进行关闭操作。举个例子
try{。。。 } catch{。。。 } finally {try {if (connection != null){ // 判断连接是否为空connection.close(); // 关闭连接}} catch (SQLException e) { // 加入关闭操作的异常捕获e.printStackTrace();}try {if (ps != null) {ps.close();}} catch (SQLException e) {e.printStackTrace();} }
三、封装
经过观察发现,1、2、7三步的基本类似,可以偷懒共同的方法,可以封装起来,甚至写成一个类,即:
共同的代码———> 方法 ———> 类
1、2、7三步的代码 ———> 分别封装成方法 ———> 放在同一个类中(工具层)
- 这种类存放在工具层,这个类就成为"工具包"
1、 工具类 Utils
- 用于存放各种封装起来的方法,提供给其他模块调用
2、封装第一步和第二步 加载驱动建立连接
封装1+2步
public Connection getConnection (){try {// 1、加载驱动Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://127.0.0.1:3306/goods_db?" +"useUnicode=true&" +"characterEncoding=UTF-8&useSSL=false";String user = "root";String password = "root";// 2、建立连接Connection connection = DriverManager.getConnection(url,user,password);return connection; // 连接成功则返回连接} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();}return null; // 连接失败则返回空 }
但是存在一个问题,URL,用户名,密码都是不固定的,这时候就需要用到配置文件
*.properties
” 、xml
或yml
- 如何使用配置文件?
3、properties配置文件的使用
键值对格式 :
key=value
- 注意:等号的两边都不能有空格
具体使用步骤
将配置文件 拷贝到 项目工程目录 下
读取配置文件的值
要有对应的库 ——> 找到对应的或对象 ——> 方法
Java有对应的类
Properties
,实现的思路如下:- 读取文件 调用
InputStream
类 (IO流的内容 后续会接触到 - 实例化属性类
Properties
- 调用
load(文件名)
加载文件 - 取值 用
getProperty(键名)
来搜索对应的数据,返回值类型为String
- 读取文件 调用
举个例子
public static void main(String[] args) {try {// 用IO读取文件InputStream inputStream = new FileInputStream("db.properties");// 加载Properties pps = new Properties();pps.load(inputStream);// 获取字符串String driver = pps.getProperty("driver");System.out.println(driver);} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} }
在工具类中,获取对应的驱动,url,用户名,密码存放在String
在执行连接数据库时,直接调用这些字符串进行登陆即可
- 在实际应用场景中,只需要读取一次配置文件。那么,如何只读取一次配置文件?
- 构造函数?实例化的时候只运行一次,但是多次实例化还会再次执行
- 这里就需要用到静态代码块——
- 语法:
static {代码块}
- 在类里的静态代码块,只会执行一次
- 执行的时间是在构造函数之前,且需要实例化的时候才会运行
- 语法:
4、封装第七步:关闭操作
举个例子
public void closeJdbc(Connection con , PreparedStatement ps , ResultSet rs){try {if (rs != null){rs.close();}} catch (SQLException e) {e.printStackTrace();}try {if (con != null){ // 判断连接是否为空con.close(); // 关闭连接}} catch (SQLException e) { // 加入关闭操作的异常捕获e.printStackTrace();}try {if (ps != null) {ps.close();}} catch (SQLException e) {e.printStackTrace();} }
5、调用思路
思路如下:
- 先将工具类实例化为全局变量 (所有需要关闭的对象也要声明为全局变量)
- 调用工具类的方法
getConnection ()
获取 连接 Connection- 对应的完成了第一步和第二步
- 继续完成 写SQL语句 预编译 执行和获取结果的步骤
- 在最后的finally的语句块中调用关闭的方法
closeJdbc()
,关闭掉对应的对象。- 由于关闭方法有多个对象,当不存在某个对象时,可以传入
null
- 由于关闭方法有多个对象,当不存在某个对象时,可以传入
6、工具类的具体案例
举个例子
Connection connection = null; PreparedStatement ps = null; ResultSet resultSet = null; JdbcUtils jdbcUtils = new JdbcUtils(); connection = jdbcUtils.getConnection(); // 调用方法获得连接 try {String sql = "SELECT * FROM tb_user WHERE userid = ? OR username = ?"; // 预编译ps = connection.prepareStatement(sql);ps.setString(1, useridText);ps.setString(2, usernameText);resultSet = ps.executeQuery();if (resultSet.next()) {JOptionPane.showMessageDialog(null, "账号已重复!","注意", JOptionPane.WARNING_MESSAGE);return;} else {// 账号没有重复 可以继续执行操作 。。。} } catch (SQLException e) {e.printStackTrace(); } finally {jdbcUtils.closeJdbc(connection, ps, resultSet);// 如果没有resultset,就传入null即可 }
【Java学习笔记】 MYSQL03 学习使用JDBC访问数据 以及 JDBC的优化和封装相关推荐
- JDBC学习笔记02【ResultSet类详解、JDBC登录案例练习、PreparedStatement类详解】
黑马程序员-JDBC文档(腾讯微云)JDBC笔记.pdf:https://share.weiyun.com/Kxy7LmRm JDBC学习笔记01[JDBC快速入门.JDBC各个类详解.JDBC之CR ...
- WinDbg学习笔记(二)--字符串访问断点
标 题: [原创]WinDbg学习笔记(二)--字符串访问断点 作 者: gaorqing 时 间: 2009-07-25,21:39:04 链 接: http://bbs.pediy.com/sho ...
- 【Springboot学习笔记】SpringBoot+Mybatis+Thymeleaf+Layui数据表单从零开始实现按条件模糊分页查询的方法
[Springboot学习笔记]SpringBoot+Mybatis+Thymeleaf+Layui数据表单从零开始实现按条件模糊分页查询的方法 目录 1.搭建环境 1.1直接从网上下载SpringB ...
- Kafka学习笔记(3)----Kafka的数据复制(Replica)与Failover
1. CAP理论 1.1 Cosistency(一致性) 通过某个节点的写操作结果对后面通过其他节点的读操作可见. 如果更新数据后,并发访问的情况下可立即感知该更新,称为强一致性 如果允许之后部分或全 ...
- Kinect开发学习笔记之(七)骨骼数据的提取
Kinect开发学习笔记之(七)骨骼数据的提取 zouxy09@qq.com http://blog.csdn.net/zouxy09 我的Kinect开发平台是: Win7x86 + VS2010 ...
- SilverLight学习笔记--进一步学习Isolated Storage独立存储一(理论篇)
在"silverlight如何在客户端读取文件"以及"silverlight如何在客户端写入文件"两篇文章中我们初步接触了Isolated Storage概念. ...
- at24c16如何划分出多个读写区_AVR学习笔记九、基于AT24C16的数据存储实验
Ema{@AVR 学习笔记九.基于 AT24C16 的数据存储实验 ------- 基于 LT_Mini_M16 9.1 用 I/O 口模拟 I2C 总线实现 AT24C16 的读写 9.1.1 .实 ...
- oracle 11g dul,学习笔记:Oracle dul数据挖掘 导出Oracle11G数据文件坏块中表中
试验模拟导出Oracle 11G数据库中数据文件坏块中表中的数据 以前一直以为dul对应的版本只能恢复最高的数据库版本一致,今天测试发现dul 10可以恢复11g最新版的数据库. 模拟环境SQL> ...
- Python3学习笔记之-学习基础(第三篇)
Python3学习笔记之-学习基础(第三篇) 文章目录 目录 Python3学习笔记之-学习基础(第三篇) 文章目录 一.循环 1.for循环 2.while循环 3.break,continue 二 ...
- 强化学习笔记-强化学习概述
强化学习笔记-强化学习概述 机器学习分类 强化学习与监督学习的异同点 强化学习基本原理 强化学习解决的是什么样的问题 强化学习分类 请分别解释随机性策略和确定性策略 回报.值函数.行为值函数三个指标的 ...
最新文章
- DAY11-MYSQL之ORM框架SQLAlchemy
- 操作系统(二十二)用信号量机制实现进程互斥、同步、前驱关系
- struts2的处理流程
- opencv及相机相关6
- 理解lua中 . : self
- Python 装饰器理解
- Java 面试 80% 的人都会踩这些坑,你知道几种?
- blade php代码,Laravel 5框架学习之Blade 简介
- SpringMVC 的总结
- GitHub Universe 2020 强势登陆,GitCode直播已上线
- 6. 分类图显示和保存
- python︱Anaconda安装、简介(安装报错问题解决、Jupyter Notebook)
- oracle 11g安装自己理解
- mysql 如何避免间隙锁_mysql 间隙锁
- 网络安全-MySQL数据库
- Arm Compiler for Embedded 6 编译器工具链常用选项
- Leedcode 875. 爱吃香蕉的珂珂
- python字体类型arial_python-3.x - 为什么我的font.name属性不影响使用Python-pptx制作的ppt上的字体? 我总是得到arial字体 - 堆栈内存溢出...
- windows下 编写的Qt程序连接远程MySQL数据库
- git推送被拒绝可能的原因
热门文章
- kalibr fov畸变模型
- 怎样下载网页上的视屏到本地
- 使用LIME解释CNN
- 动环监控系统服务器维护,机房动环设备维护与检测的13个具体内容
- rtlinux linux实时补丁,(九)RTLinux补丁以及cyclictest
- python 正则表达式 compile_使用compile()函数编译正则表达式【Python技术文章】
- 2019中兴通讯软件开发岗c/c++方向(笔试+面试)总结
- 四色定理java_java – 四色定理的递归算法
- lucas–kanade_Lucas–Kanade光流算法
- 基于Arch GNU/Linux的简体中文live系统 archlive