当前位置: 首页 > news >正文

JDBC学习,从入门到入土

JDBC引入

JDBC概念:

JDBC是使用Java语言操作关系型数据库的一套API。全称:(Java DataBase Connectivity)Java数据库连接

JDBC的本质:

官方定义的一套操作所有关系型数据库的规则,即接口

各个数据库厂商去实现这套接口,即提供实现类,这些实现类也叫做驱动, 厂商提供的是相应的数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行的是驱动jar包中的实现类。

JDBC的好处:

各数据库厂商使用相同的接口,Java代码不需要针对不同的数据库分别开发。可随时替换底层数据库,访问数据库的Java代码基本不变。

JDBC的使用步骤

有七步,如代码所示:

package JDBC学习;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class test1 {public static void main(String[] args) {Connection conn = null;Statement sta = null;try {//1 注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//2 获取连接String url = "jdbc:mysql://127.0.0.1:3306/limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url, username, password);//3 定义SQLString sql_1 = "UPDATE emp1 SET salary = 20000 WHERE `name` = 'Tom'";//4 获取执行sql的对象Statementsta = conn.createStatement();//5 执行sqlint i = sta.executeUpdate(sql_1);//i为受影响的行数//6 处理结果System.out.println(i);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (SQLException e) {e.printStackTrace();} finally {//7 释放资源try {sta.close();} catch (SQLException e) {e.printStackTrace();}try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}

注:mysql5.0之后可以省略注册驱动一步

JDBC API详解

DiverManager

DiverManager(驱动管理类)作用:

  1. 注册驱动
  2. 获取数据库连接

关于DiverManager中的静态方法static Connection getConnection(String url,String user,String password)

参数:
  1. url:连接路径

  1. user:用户名
  2. password:密码

Connection

Connection(数据库连接对象)作用:

  1. 获取执行SQL的对象
  2. 管理事务

获取执行SQL的对象

  • 普通执行SQL对象

Statement createStatement()

  • 预编译SQL的执行SQL对象:防止SQL注入

PreparedStatement preparedStatement(sql)

  • 执行存储变量的对象

CallableStatement prepareCall(sql)

 事务管理

 可以利用JDBC的三个方法来管理事务:

package JDBC学习;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;public class test2 {public static void main(String[] args) {Connection conn = null;Statement sta = null;try {//1 注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//2 获取连接String url = "jdbc:mysql://127.0.0.1:3306/limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url, username, password);//3 定义SQLString sql_1 = "UPDATE emp1 SET salary = 20000 WHERE `name` = 'Tom'";String sql_2 = "UPDATE emp1 SET salary = 20000 WHERE `name` = '丘丘人'";//4 获取执行sql的对象Statementsta = conn.createStatement();//开启事务conn.setAutoCommit(false);//5 执行sqlint i = sta.executeUpdate(sql_1);//i为受影响的行数int j = sta.executeUpdate(sql_2);//i为受影响的行数//6 处理结果System.out.println(i);System.out.println(j);//提交事务conn.commit();} /*catch (ClassNotFoundException e) {e.printStackTrace();} */catch (SQLException e) {//回滚事务try {conn.rollback();} catch (SQLException ex) {e.printStackTrace();}e.printStackTrace();} finally {//7 释放资源try {sta.close();} catch (SQLException e) {e.printStackTrace();}try {conn.close();} catch (SQLException e) {e.printStackTrace();}}}
}

先设置MySQL不自动提交事务,在try中末尾处加上提交事务的操作。如果出现异常,说明此异常操作的事务不应该提交,要回滚事务。将回滚事务的操作放在catch中,随着和对异常的处理操作一起进行回滚操作

Statement

Statement作用:

执行SQL语句。

执行SQL语句

int executeUpdate(sql):执行DML、DDL语句

返回值:①DML语句影响的行数 ②DDL语句执行后,执行成功也可能返回0

ResultSet executeQuery(sql):执行DQL语句

返回值:ResultSet结果集对象

ResultSet

Result(结果集对象)作用:

封装了DQL查询语句的结果

ResultSet executeQuery(sql):执行DQL语句

返回值:ResultSet结果集对象

获取查询结果

boolean next():①将指针从当前位置移动到下一行 ②判断当前行是否为有效行

返回值:true,有效行,当前行有数据;false,无效行,当前行没有数据。

xxx getXxx(参数):获取数据

xxx:数据类型。如int getInt()、String getString(参数)

参数:int,列的编号,从1开始。String:列的名称。

使用

使用时通常会用上while循环

while(…….next()){

……

…….getXxx(参数);

}

例:查询员工表emp1中的数据并打印。

@Test
void test3() {Connection conn = null;Statement sta = null;ResultSet rs = null;try {//获取连接(注册驱动已省略)String url = "jdbc:mysql:///limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url,username,password);//定义SQL语句String sql_1 = "select * from emp1";//获取statement对象sta = conn.createStatement();//执行sqlrs = sta.executeQuery(sql_1);//处理结果,遍历查询的所有结果while(rs.next()){int id = rs.getInt("id");String name = rs.getString(2);Date date = rs.getDate(3);double salary = rs.getDouble("salary");System.out.print(id + "\t");System.out.print(name + "\t");System.out.print(date + "\t");System.out.print(salary + "\t");System.out.println();}} catch (SQLException e) {e.printStackTrace();} finally {//释放资源try {rs.close();sta.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}
}

还可以使用其查询数据做Java代码的处理,例:将员工的sal添加到一个Arraylist中。

@Test
void test4() {Connection conn = null;Statement sta = null;ResultSet rs = null;try {//获取连接(注册驱动已省略)String url = "jdbc:mysql:///limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url,username,password);//定义SQL语句String sql_1 = "select salary from emp1";//获取statement对象sta = conn.createStatement();//执行sqlrs = sta.executeQuery(sql_1);//处理结果,遍历查询的所有结果ArrayList<Double> sal = new ArrayList<>();while(rs.next()){double salary = rs.getDouble("salary");sal.add(salary);}Iterator ii = sal.iterator();while (ii.hasNext()){System.out.println(ii.next());}} catch (SQLException e) {e.printStackTrace();} finally {//释放资源try {rs.close();sta.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}
}

例:将员工的信息添加到一个Arraylist中。

@Test
void test5() {Connection conn = null;Statement sta = null;ResultSet rs = null;try {//获取连接(注册驱动已省略)String url = "jdbc:mysql:///limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url,username,password);//定义SQL语句String sql_1 = "select * from emp1";//获取statement对象sta = conn.createStatement();//执行sqlrs = sta.executeQuery(sql_1);//处理结果,遍历查询的所有结果ArrayList<Employee> employees = new ArrayList<>();while(rs.next()){int id = rs.getInt(1);String name = rs.getString("name");Date date = rs.getDate(3);double salary = rs.getDouble("salary");employees.add(new Employee(id,name,date,salary));}Iterator ii = employees.iterator();while (ii.hasNext()){System.out.println(ii.next());}} catch (SQLException e) {e.printStackTrace();} finally {//释放资源try {rs.close();sta.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}
}

PreparedStatement

PreparedStatement作用:

预编译SQL语句并执行:预防SQL注入问题

SQL注入

即利用SQL语句的语法,在填入时,强制查询结果为true。

操作

①获取PrepareStatement对象

//SQL语句中的参数值,使用?占位符替代
String sql = "SELECCT * FROM user WHERE username = ? AND password = ?";//通过Connection对象获取,并传入相应的SQL语句。
PreparedStatement psta = conn.prepareStatement(sql);

②设置参数值

PreparedStatement对象:setXxx(参数1,参数2):给?赋值

Xxx指的是数据类型,参数1是?的顺序编号,从一开始。参数2是?的具体的值

③执行SQL

使用:executeUpdate()/executeQuery():不需要再传入SQL语句。

例:

@Test
void test7()
{Connection conn = null;PreparedStatement psta = null;ResultSet rs = null;try {//获取连接String url = "jdbc:mysql:///limingmao";String username = "liergou";String password = "liergou070509";conn = DriverManager.getConnection(url,username,password);//接收用户输入的用户名和密码String uname = "张三";String pwd = "1234";//定义SQLString sql = "SELECT * FROM tb_user WHERE username = ? AND password = ?";//获取psta对象psta = conn.prepareStatement(sql);//设置?的值psta.setString(1,uname);psta.setString(2,pwd);//执行SQL语句rs = psta.executeQuery();//判断是否成功if(rs.next()) {System.out.println("登录成功");}else {System.out.println("登录失败");}} catch (SQLException e) {e.printStackTrace();} finally {try {//释放资源rs.close();psta.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}
}

PreparedStatement原理

  1. 在获取PreparedStatement对象时,将SQL语句发送给MySQL服务器进行检查、编译
  2. 执行时就不用再进行这些步骤了,速度更快
  3. 如果SQL模板一样,则只需要进行一次检查、编译

PreparedStatement好处:

  1. 预编译SQL,性能更高
  2. 防止SQL注入:将敏感字符进行转义

开启预编译功能:

userServerPrepStmts=true:将此参数键值对放到url的参数键值对处。

数据库连接池

简介

数据库连接池是个容器,负责分配、管理数据库连接(Connection)

它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

释放空闲时间超过最大空闲时间的数据库连接来避免因为没有释放数据库连接而引起的数据库连接遗漏

好处:

  • 资源重用
  • 提升系统响应速度
  • 避免数据库连接遗漏

数据库连接池实现

标准接口:DataSource

官方提供的数据库连接池标准接口,由第三方组织实现此接口。

功能:获取连接

Connection getConnection()

常见的数据库连接池:

  • DBCP
  • C3P0
  • Druid

Druid(德鲁伊)

Druid连接池是阿里巴巴开源的数据库连接池项目

功能强大,性能优秀,是Java语言最好的数据库连接池之一

使用步骤以及代码实现如下:

public class test_druid {public static void main(String[] args){try {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("D:\\李明茂\\Java学习\\JDBC\\src\\druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接ConnectionConnection conn = dataSource.getConnection();System.out.println(conn);} catch (Exception e) {e.printStackTrace();}}
}

JDBC练习:实现品牌列表的增删查改

要求:使用数据库连接池(德鲁伊),使用预编译防SQL注入的PreparedStatement

题目准备:

数据库准备:

CREATE TABLE tb_brand(
id INT PRIMARY KEY AUTO_INCREMENT,
brand_name VARCHAR(20),-- 品牌名称
company_name VARCHAR(20),-- 企业名称
ordered INT,-- 排序字段
description VARCHAR(100),-- 描述信息
`status` INT-- 状态 0表示禁用,1表示启用
);INSERT INTO tb_brand(brand_name,company_name,ordered,description,`status`)
VALUES('金坷拉','金坷垃股份有限公司',5,'要种庄稼,必须要有金坷垃',0),
('米哈游','米哈游技术有限公司',100,'技术宅拯救世界',1),
('腾讯','腾讯技术有限公司',50,'下元梦之心',1);SELECT * FROM tb_brand;DESC tb_brand;

Java中Brand类的准备:

public class Brand {
private Integer id;
private String brandName;
private String companyName;
private Integer ordered;
private String description;
private Integer status;public Brand() {}public Brand(Integer id, String brandName, String companyName, Integer ordered, String description, Integer status) {this.id = id;this.brandName = brandName;this.companyName = companyName;this.ordered = ordered;this.description = description;this.status = status;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getBrandName() {return brandName;}public void setBrandName(String brandName) {this.brandName = brandName;}public String getCompanyName() {return companyName;}public void setCompanyName(String companyName) {this.companyName = companyName;}public Integer getOrdered() {return ordered;}public void setOrdered(Integer ordered) {this.ordered = ordered;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}@Overridepublic String toString() {return "Brand{" +"id=" + id +", brandName='" + brandName + '\'' +", companyName='" + companyName + '\'' +", ordered=" + ordered +", description='" + description + '\'' +", status=" + status +'}';}
}

开始练习:

查所有数据:(单元测试方法中实现,下同)

/*** 查询所有* SQL语句:SELECT * FROM tb_brand;* 参数:不需要* 结果:List<Brand>*/@Testpublic void testSelectAll(){Connection conn = null;PreparedStatement pstmt = null;ResultSet rs = null;try {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("D:\\李明茂\\Java学习\\JDBC\\src\\druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connectionconn = dataSource.getConnection();//定义SQL语句String sql = "SELECT * FROM tb_brand";//获取PreparedStatement对象pstmt = conn.prepareStatement(sql);//执行SQL语句rs = pstmt.executeQuery();//处理结果List<Brand> brands = new ArrayList<>();while(rs.next()){brands.add(new Brand(rs.getInt("id"),rs.getString(2),rs.getString(3),rs.getInt(4),rs.getString("description"),rs.getInt(6)));}Iterator ii = brands.iterator();while (ii.hasNext()){System.out.println(ii.next());}} catch (Exception e) {e.printStackTrace();} finally {try {rs.close();pstmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}

增:

/*** 添加* SQL语句:* INSERT INTO tb_brand(brand_name,company_name,ordered,description,`status`) VALUES(?,?,?,?,?);* 参数:需要,除了id之外的所有参数,共五个。*/@Testpublic void testAdd(){Connection conn = null;PreparedStatement pstmt = null;//假设接受到的添加的信息如下:String brandName = "网易";String companyName = "网易技术有限公司";Integer ordered = 1;String description = "下蛋仔派对";Integer status = 1;try {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("D:\\李明茂\\Java学习\\JDBC\\src\\druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connectionconn = dataSource.getConnection();//定义SQL语句String sql = "INSERT INTO tb_brand(brand_name,company_name,ordered,description,`status`) VALUES(?,?,?,?,?);";//获取PreparedStatement对象pstmt = conn.prepareStatement(sql);//设置参数pstmt.setString(1,brandName);pstmt.setString(2,companyName);pstmt.setInt(3,ordered);pstmt.setString(4,description);pstmt.setInt(5,status);//执行SQL语句int count = pstmt.executeUpdate();//处理结果System.out.println(count > 0);} catch (Exception e) {e.printStackTrace();} finally {try {pstmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}

改:

/*** 修改* SQL语句:UPDATE tb_brand SET brand_name = ?,company_name = ?,ordered = ?,description = ?,status = ? WHERE id = ?;*/@Testpublic void testUpdate(){Connection conn = null;PreparedStatement pstmt = null;//假设接受到的添加的信息如下:String brandName = "网易";String companyName = "网易技术有限公司";Integer ordered = 1;String description = "66666";Integer status = 1;Integer id = 4;try {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("D:\\李明茂\\Java学习\\JDBC\\src\\druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connectionconn = dataSource.getConnection();//定义SQL语句String sql = "UPDATE tb_brand SET brand_name = ?,company_name = ?,ordered = ?,description = ?,status = ? WHERE id = ?;";//获取PreparedStatement对象pstmt = conn.prepareStatement(sql);//设置参数pstmt.setString(1,brandName);pstmt.setString(2,companyName);pstmt.setInt(3,ordered);pstmt.setString(4,description);pstmt.setInt(5,status);pstmt.setInt(6,id);//执行SQL语句int count = pstmt.executeUpdate();//处理结果System.out.println(count > 0);} catch (Exception e) {e.printStackTrace();} finally {try {pstmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}

删:

/*** 删除* SQL语句:DELETE FROM tb_brand WHERE id = ?;*/@Testpublic void testDelete(){Connection conn = null;PreparedStatement pstmt = null;//假设接受到的添加的信息如下:Integer id = 4;try {//加载配置文件Properties prop = new Properties();prop.load(new FileInputStream("D:\\李明茂\\Java学习\\JDBC\\src\\druid.properties"));//获取连接池对象DataSource dataSource = DruidDataSourceFactory.createDataSource(prop);//获取数据库连接Connectionconn = dataSource.getConnection();//定义SQL语句String sql = "DELETE FROM tb_brand WHERE id = ?;";//获取PreparedStatement对象pstmt = conn.prepareStatement(sql);//设置参数pstmt.setInt(1,id);//执行SQL语句int count = pstmt.executeUpdate();//处理结果System.out.println(count > 0);} catch (Exception e) {e.printStackTrace();} finally {try {pstmt.close();conn.close();} catch (SQLException e) {e.printStackTrace();}}}

相关文章:

  • 如何搭建Web自动化测试框架?
  • MyBatis:动态 SQL 标签
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • C语言数据结构-排序
  • flutter + firebase 云消息通知教程 (android-安卓、ios-苹果)
  • 【爬虫软件】孔夫子二手书采集
  • Java 中的内部类的定义
  • python异常之try/else分句
  • 基于比较的排序算法总结(java实现版)
  • 175.【2023年华为OD机试真题(C卷)】API集群负载统计(遍历和条件判断实现JavaPythonC++JS)
  • 【Docker】升级docker或者docker到docker-ce完全保留镜像和容器,不影响原容器使用方法
  • 论文笔记 | Nature 2023 FunSearch:利用大语言模型在数学科学领域探索新的发现
  • 使用yarn安装electron时手动选择版本
  • docker运行java程序的Dockerfile
  • Mybatis之增删改查
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • 【RocksDB】TransactionDB源码分析
  • 2017 前端面试准备 - 收藏集 - 掘金
  • Asm.js的简单介绍
  • Docker: 容器互访的三种方式
  • Javascript设计模式学习之Observer(观察者)模式
  • laravel5.5 视图共享数据
  • mysql 5.6 原生Online DDL解析
  • python docx文档转html页面
  • 创建一种深思熟虑的文化
  • 动态魔术使用DBMS_SQL
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 一道闭包题引发的思考
  • ​云纳万物 · 数皆有言|2021 七牛云战略发布会启幕,邀您赴约
  • #HarmonyOS:软件安装window和mac预览Hello World
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #快捷键# 大学四年我常用的软件快捷键大全,教你成为电脑高手!!
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • $L^p$ 调和函数恒为零
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (ros//EnvironmentVariables)ros环境变量
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (第8天)保姆级 PL/SQL Developer 安装与配置
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)
  • (五)大数据实战——使用模板虚拟机实现hadoop集群虚拟机克隆及网络相关配置
  • . NET自动找可写目录
  • .NET Core IdentityServer4实战-开篇介绍与规划
  • .NET/C# 在 64 位进程中读取 32 位进程重定向后的注册表
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .NetCore部署微服务(二)
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .net反混淆脱壳工具de4dot的使用
  • .net开发引用程序集提示没有强名称的解决办法
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .sdf和.msp文件读取