今日内容
零、 复习昨日
一、作业
二、SQL注入
三、PreparedStatement
四、事务
五、DBUtil
零、 复习昨日
一、引言
1.1 如何操作数据库
使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写 SQL 语句,点击执行,查看操作结果(结果集或受影响行数)。
客户端操作数据库步骤 |
---|
1.2 实际开发中,会采用客户端操作数据库吗?
在实际开发中,当用户的数据发生改变时,不可能通过客户端操作执行 SQL 语句,因为操作量过大,无法保证效率和正确性。
二、JDBC
2.1 什么是 JDBC?
JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作。
2.2 JDBC 核心思想
Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。
核心思想 |
---|
2.2.1 MySQL 数据库驱动
- mysql-connector-java-5.1.X.jar 适用于 5.X 版本
- mysql-connector-java-8.0.X.jar 适用于 8.X版本
ps: 常识
jar包其实就是一种压缩包,其中就是一个java项目
mysql-connector-java-5.1.X.jar 中就是mysql厂商根据jdbc协议提供一些实现代码
2.3 环境搭建
mysql厂商提供的jdbc规范的实现,要想完成JDBC操作,就需要将驱动包加入到当前项目中.
2.3.1 idea导入类库
打开项目结构(Project Structure) |
---|
选择libraries,添加jar包 |
---|
本地磁盘选择jar包 |
---|
应用生效 |
---|
下方,External查看导入类库 |
---|
2.3.2 maven依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
<!-- <version>8.0.29</version> -->
</dependency>
2.3.3 测试
public class TestJDBC {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 这个是java反射机制
* 通过类路径将mysql驱动包文件加载到jvm
*/
Class.forName("com.mysql.jdbc.Driver");
System.out.println("OK" );// 只要不报错,就说明jar包导入成功
}
}
三、JDBC编程
JDBC编程有标准步骤(八股文)
- 注册驱动
- 将sql语句的运行环境加载到JVM
- 连接数据库
- 获得执行SQL的对象
- 执行SQL语句,获得结果
- 关流
3.1 注册驱动
Class.forName("com.mysql.jdbc.Driver");//5.7版本 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");//5.8版本 加载驱动
3.2 连接数据库
- 通过 DriverManager.getConnection(url,user,password) 获取数据库连接对象
- URL:jdbc:mysql://localhost:3306/database
- ?useUnicode=true&characterEncoding=utf8 // 解决数据编码格式乱码
- &useSSL=false // 解决执行时控制台红色警告
- &serverTimezone=UTC // mysql8版本需要加时区
- username:root
- password:123456
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/数据库名字?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=UTC ", "数据库用户名","数据库密码");
- URL(Uniform Resource Locator) 统一资源定位符:由协议、IP、端口、SID(程序实例名称)组成
3.3 获取发送 SQL 的对象
通过 Connection 对象获得 Statement 对象,用于对数据库进行通用访问。
Statement statement = conn.createStatement();
3.4 执行SQL 语句
执行 SQL 语句并接收执行结果。
String sql ="INSERT INTO t_jobs(JOB_ID,JOB_TITLE,MIN_SALARY,MAX_SALARY) VALUES('JAVA_Le','JAVA_Lecturer',4000,10000);";
int result = statement.executeUpdate(sql);//执行SQL语句并接收结果
- 注意:在编写 DML 语句时,一定要注意字符串参数的符号是单引号 ‘值’
- DML 语句:增删改时,返回受影响行数(int 类型)。
- DQL 语句:查询时,返回结果数据(ResultSet 结果集)。
3.5 处理结果
接受处理操作结果。
if(result == 1){
System.out.println("Success");
}
- 受影响行数:逻辑判断、方法返回。
- 查询结果集:迭代、依次获取。
3.6 释放资源
遵循先开后关原则,释放所使用到的资源对象。
statement.close();
conn.close();
3.7 案例
准备数据库表,进行CRUD.
create table tb_user(
id int(11) primary key auto_increment comment '用户编号',
username varchar(10) comment '用户名',
password varchar(10) comment '密码',
phone varchar(11) comment '手机号',
create_time date comment '注册时间',
money double(10,2) comment '账户余额',
sex int(1) comment '性别 1男2女'
);
需求: 使用JDBC完成对tb_user表插入数据
package com.qf.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 演示JDBC
*/
public class Demo1_insert {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1 加载驱动
// ps: 利用反射技术,将驱动类加载到JVM
Class.forName("com.mysql.jdbc.Driver");
// 2 通过驱动管理对象获得连接对象
/**
* 参数1 url: 数据库连接的地址
* 协议://ip:端口/库名
* 参数2 username: 数据库用户名
* 参数3 password: 数据库密码
*/
String url = "jdbc:mysql://localhost:3306/java2311?useSSL=false&serverTimezone=UTC";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url,username,password);
// 3 通过连接对象,创建执行sql语句的对象
Statement statement = conn.createStatement();
// 4 通过执行语句对象,执行sql,获得结果
String sql = "insert into tb_user (id,username,password,phone,create_time,money,sex) values (2,'root','123456','1122200','2022-11-21',2000.0,2)";
// 执行查询,是executeQuery()
// 执行增删改,是executeUpdate(),返回受影响的行数
int num = statement.executeUpdate(sql);
if (num > 0) {
System.out.println("插入成功!!" );
}
// 5 关流
statement.close();
conn.close();
}
}
四、完成增删改
4.1 插入
参考入门案例
4.2 更新
任何的JDBC都是那5个步骤.
package com.qf.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 更新
*/
public class Demo2_update {
public static void main(String[] args) throws Exception {
// 1 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 通过驱动管理对象获得连接对象
String url = "jdbc:mysql://localhost:3306/java2311?useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
// 3 通过连接对象创建执行语句对象
Statement statement = conn.createStatement( );
// 4 通过执行语句对象执行sql,获得结果
String sql = "update tb_user set username = '小孟', phone = '666666' where id = 3";
int num = statement.executeUpdate(sql);
if (num > 0) {
System.out.println("更新成功!" );
}
// 5 将对象的流关闭
statement.close();
conn.close();
}
}
4.3 删除
package com.qf.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
public class Demo3_delete {
public static void main(String[] args) {
Statement statement = null;
Connection conn = null;
try {
// 1 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 获得连接
String url = "jdbc:mysql://localhost:3306/java2311?useSSL=false";
String username = "root";
String password = "123456";
conn = DriverManager.getConnection(url, username, password);
// 3 获得语句对象
statement = conn.createStatement( );
// 4 执行sql
int num = statement.executeUpdate("delete from tb_user where id = 3");
if (num > 0) {
System.out.println("删除成功" );
}
}catch (Exception e) {
// 如果有异常,要打印出来,因为要根据异常解决问题
e.printStackTrace();
} finally {
try {
// 5 关闭连接
statement.close( );
conn.close( );
}catch (SQLException e) {
e.printStackTrace();
}
}
}
}
五、查询结果集ResultSet【重要】
查询返回的是一种虚拟表,Java的JDBC中是使用结果集(ResultSet)来封装这个虚拟表,结果集就是一个集合,内部就存储了列名和每行数据,那么学习查询的重点是
- 从结果集取值
package com.qf.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.*;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
public class Demo4_select {
public static void main(String[] args) throws Exception{
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
Statement statement = conn.createStatement( );
/**
* 执行查询方法 executeQuery()
* 返回值是 ResultSet 结果集,其中就包含查询返回的所有数据(一张虚拟表)
* ResultSet结果集中包含列和行数据,其中有个光标指向表头
* next() 方法会向下移动一行,返回boolean,为true即有下一行数据,false该行没数据
* 当指向该行后,有方法可以获取该行列值
* getXxx() ps:xxx是各种数据类型
* getXxx(String columnLabel) 通过列名取值,如果有别名要使用别名
*/
String sql = "select birthday,money,username,password,id,sex,age from tb_user";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()){
int id = rs.getInt("id");
String username = rs.getString("username");
String password = rs.getString("password");
String sex = rs.getString("sex");
int age = rs.getInt("age");
Date birthday = rs.getDate("birthday");
double money = rs.getDouble("money");
System.out.println(id+"-"+username+"-"+password+"-"+sex+"-"+age+"-"+birthday+"-"+money);
}
rs.close();
statement.close();
conn.close();
}
}
六、登录案例【重要】
需求:
- 通过控制台用户输入用户名和密码。
- 用户输入的用户名和密码作为条件,编写查询 SQL 语句。
- select * from user where username = xxx and password = xxx
- 如果该用户存在,提示登录成功,反之提示失败。
package com.qf.jdbc;
import com.mysql.jdbc.Driver;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc
*/
public class Demo5_Login {
public static void main(String[] args) {
// 1 输入用户名和密码
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:" );
String username = scanner.nextLine( );
System.out.println("请输入密码:" );
String password = scanner.nextLine( );
// 2 根据用户名和密码查人
boolean isOk = findUserByLogin(username,password);
// 3 结果
if (isOk) {
System.out.println("登录成功!" );
} else {
System.out.println("用户名或密码错误!" );
}
}
// 使用捕获代码完成
private static boolean findUserByLogin(String username, String password) {
Connection conn = null;
Statement statement = null;
boolean isOk = false;
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/2311?useSSL=false", "root", "123456");
statement = conn.createStatement( );
// 根据用户名和密码查询,注意字符串拼接.特别注意单引号
ResultSet rs = statement.executeQuery("select * from tb_user where username = '"+username+"' and password = '"+password+"'");
// 只要有值,就说明数据库有这个信息,登录成功
if (rs.next()) {
// System.out.println("登录成功!" );
int id = rs.getInt("id");
String uname= rs.getString("username");
// ...
System.out.println(id+"-"+username);
isOk = true;
} else {
// System.out.println("用户名或密码错误!!" );
}
}catch (Exception e) {
System.out.println("SQL操作出错!" );
e.printStackTrace();// 打印异常
} finally {
try{
statement.close();
conn.close();
}catch (Exception e) {
System.out.println("关流异常" );
e.printStackTrace();// 打印异常
}
}
return isOk;
}
}
七、ORM【重要】
7.1 什么是ORM
目前使用JDBC完成了CRUD,但是现在是进行CRUD,增删改方法要设计很多参数,查询的方法需要设计集合才能返回.
在实际开发中,我们需要将零散的数据封装到对象处理.
ORM (Object Relational Mapping) 对象关系映射
是指
数据库表
与Java的实体类
有关系,可以进行映射
- 数据库表 --> Java的类
- tb_user —> User.java
- 字段 --> 类的属性
- id int --> private int id;
- username varchar --> private String username;
- …
- 一行数据 --> 类的对象
- 一行数据内每个列的值 --> 对象的属性值
7.2 实体类
实体类: 数据表中零散数据的载体,用来封装数据.
- 表名 设计 类名
- 将列名设计成属性名
- id --> id
- create_time --> createTime (下划线转驼峰)
- 将列的数据类型设计成属性的数据类型
- 给类提供对应set get
一般项目中一个表就会对应一个实体类,所有的实体类都会放在model/entity/pojo/javabeen包结构中
将来写项目,数据库设计完,搭建完项目,第一件事件就是根据表结构,创建实体类
package com.qf.model; // 包
public class User { // 实体类,是表名
// 属性是字段名
private int id;
private String username;
private String password;
private String phone;
private Date createTime;
private double money;
private int sex;
// setter getter...
}
7.3 ORM改造登录案例
package com.qf.jdbc;
import com.qf.model.User;
import java.sql.*;
import java.util.Scanner;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 使用orm改造login登录案例
*/
public class Demo6_login_orm {
public static void main(String[] args) {
input();
}
// 1 键盘输入
public static void input() {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = scanner.nextLine( );
System.out.println("请输入密码:");
String password = scanner.nextLine( );
// 调用方法执行查询
User user = findUserByUsernameAndPassword(username, password);
if (user != null) {
System.out.println("用户登录成功" );
System.out.println("用户信息: " + user );
} else {
System.out.println("用户名或密码错误!" );
}
}
// 2 执行登录
public static User findUserByUsernameAndPassword(String username, String password) {
Connection conn = null;
Statement s = null;
ResultSet rs = null;
// 声明user,赋值为null,下方如果登录成功,创建user对象
// 即将来,可以通过user是否为空判断是否登录成功
User user = null;
try {
// 1 驱动
Class.forName("com.mysql.jdbc.Driver");
// 2 连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 3 语句
s = conn.createStatement( );
// 4 查询
String sql = "select * from tb_user where username = '"+username+"' and password = '"+password+"'";
// 执行
rs = s.executeQuery(sql);
// 判断成功,说明查询到用户
if (rs.next()) {
// 取出数据
int id = rs.getInt("id");
String username1 = rs.getString("username");
String password1 = rs.getString("password");
String phone = rs.getString("phone");
Date createTime = rs.getDate("createTime");
double money = rs.getDouble("money");
int sex = rs.getInt("sex");
// 封装数据
user = new User();
user.setId(id);
user.setUsername(username1);
user.setPassword(password1);
user.setPhone(phone);
user.setCreateTime(createTime);
user.setMoney(money);
user.setSex(sex);
}
} catch (Exception e) {
System.out.println("出错了!" + e.getMessage( ));
} finally {
// 5 关流
try {
rs.close();
s.close( );
conn.close( );
} catch (SQLException e) {
System.out.println("关流时有异常" + e.getMessage( ));
}
}
return user;
}
}
八、SQL注入
8.1 什么是SQL注入
select * from tb_user where username = ‘111’ and password = ‘111
’
select * from tb_user where username = ‘111’ and password = ‘111' or '1=1
’
用户输入的数据中有
SQL关键词
,导致在执行SQL语句时出现一些不正常的情况.这就是SQL注入!
出现SQL注入是很危险
8.2 避免SQL注入
问题出现在用户输入数据时,里面有
关键词
,再配合字符串拼接导致
出现SQL注入.所以为了避免SQL注入,可以在用户输入数据到SQL之前,先把SQL语句预编译
,预处理后,JDBC就会知道此SQL需要几个参数,后续再将用户输入的数据给参数填充.这就是PreparedStatement
九、PreparedStatement【重点】
PreparedStatement是Statement的子接口,用来预处理SQL语句
PreparedStatement使用
- 先写SQL语句,SQL语句中的参数不能直接拼接,而是使用
?占位
- 使用ps预处理SQL语句,处理的?号,ps内部就会知道此SQL语句需要几个参数
- 再动态给?处填充值
- 执行sql
package com.qf.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 预处理语句
*/
public class Demo3 {
public static void main(String[] args) throws Exception {
// 1加载驱动
// 2获得连接
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 3获得[预处理语句]对象
/**
* 使用预处理对象有步骤
* 1 先写sql,语句中需要拼接参数的地方用?占位
* 2 通过连接对象,调用处理语句的方法,传入sql参数,对语句处理后
* 获得一个含有处理过sql的语句对象
* 3 给处理过的?处赋值
* 4 执行
*/
String sql = "select * from tb_user where username = ? and password = ?";
System.out.println("处理前:" + sql );
PreparedStatement ps = conn.prepareStatement(sql);
System.out.println("处理后:" + ps );
// 3 给?赋值
ps.setString(1,"uzi");
ps.setString(2,"123456");
System.out.println("赋值后:" + ps );
// 4执行sql语句
ResultSet rs = ps.executeQuery( );// 【特别注意: 不需要再传参数】
while(rs.next()) {
User user = new User( );
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setPhone(rs.getString("phone"));
user.setCreateTime(rs.getDate("create_time"));
user.setMoney(rs.getDouble("money"));
user.setSex(rs.getInt("sex"));
System.out.println(user );
}
// 5关流
rs.close();
ps.close();
conn.close();
}
}
使用预处理语句改造登录案例
package com.qf.jdbc;
import java.sql.*;
import java.util.Scanner;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 使用预处理语句完成登录
*/
public class Demo4_login_plus {
public static void main(String[] args) {
input();
}
// 设计方法完成输入
public static void input() {
System.out.println("欢迎登录LPL选手管理系统" );
Scanner scanner = new Scanner(System.in);
System.out.println("请输入用户名:" );
String username = scanner.nextLine( );
System.out.println("请输入密码:" );
String password = scanner.nextLine( );
User user = login(username, password);
if (user != null) {
System.out.println("欢迎进入系统:" + user );
} else {
System.out.println("用户名或密码错误!" );
}
}
public static User login(String username,String password){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
User user = null; // 初始值
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 1 先写sql,条件写?
String sql = "select * from tb_user where username = ? and password = ?";
// 2 获得预处理语句对象
ps = conn.prepareStatement(sql);
// 3 给?赋值
ps.setString(1,username);
ps.setString(2,password);
System.out.println(ps );
// 4 执行
rs = ps.executeQuery( );
while (rs.next()) {
user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setPhone(rs.getString("phone"));
user.setCreateTime(rs.getDate("create_time"));
user.setMoney(rs.getDouble("money"));
user.setSex(rs.getInt("sex"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
rs.close();
ps.close();
conn.close();
}catch (Exception e) {
e.printStackTrace();
}
}
return user;
}
}
十、预处理语句完成CRUD
10.1 插入
// 插入
public static void insert() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 1 sql
String sql = "insert into tb_user values (?,?,?,?,?,?,?)";
// 2 预处理
PreparedStatement ps = conn.prepareStatement(sql);
// 3 给?赋值
ps.setInt(1,6);
ps.setString(2,"JK");
ps.setString(3,"123456");
ps.setString(4,"5555");
/**
* setDate() 需要传入java.sql.Date包下的日期对象
* java.sql.Date没有无参构造,只有一个有参构造,传入是毫秒值
*/
// 方案1: 获得当前时间毫秒值
// java.util.Date date = new java.util.Date( );// 创建当前日期对象
// long time = date.getTime( );// 获得当前毫秒值
// 方案2: 获得指定时间的毫秒值
LocalDate localDate = LocalDate.of(2020, 10, 1);
java.util.Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
long time = date.getTime();
// 方案3: 获得系统毫秒值
//long time = System.currentTimeMillis( );// 获得当前毫秒值
ps.setDate(5,new java.sql.Date(time));
ps.setDouble(6,4800);
ps.setInt(7,1);
// 4 执行
int i = ps.executeUpdate( );
System.out.println(i > 0 ?"OK":"ERR" );
ps.close();
conn.close();
}
10.2 更新
public static void main(String[] args) throws Exception {
LocalDate localDate = LocalDate.of(1999, 10, 1);
java.util.Date date = java.util.Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
User user = new User(1,"mlxg","6666","1111",date,6300,1);
update(user);
}
// 更新
public static void update(User user) throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 1 sql
String sql = "update tb_user set username = ?,password = ? ," +
"phone = ?,create_time = ?,money = ?,sex = ? " +
"where id = ?";
// 2 预处理
PreparedStatement ps = conn.prepareStatement(sql);
// 3 给?赋值
ps.setString(1,user.getUsername());
ps.setString(2,user.getPassword());
ps.setString(3,user.getPhone());
ps.setDate(4,new java.sql.Date(user.getCreateTime().getTime()));
ps.setDouble(5,user.getMoney());
ps.setInt(6,user.getSex());
ps.setInt(7,user.getId());
// 4 执行
int i = ps.executeUpdate( );
System.out.println(i > 0 ?"OK":"ERR" );
ps.close();
conn.close();
}
10.3 删除
// 删除
public static void delete() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// 1 先写sql
String sql = "delete from tb_user where id = ?";
// 2 预处理
PreparedStatement ps = conn.prepareStatement(sql);
// 3 ?赋值
ps.setInt(1,4);
// 4 执行
int i = ps.executeUpdate( );
System.out.println(i > 0 ?"OK":"ERR" );
ps.close();
conn.close();
}
10.4 查询
// 根据id从数据库查询出用户信息
public static User getUserById(int id) throws Exception {
// 1 注册驱动
Class.forName("com.mysql.Driver");
// 2 获得连接
String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
User user = null;
// 3 预处理
// 3.1 写sql,参数用?占位
String sql = "select * from tb_user where id = ?";
// 3.2 预处理?号
PreparedStatement ps = conn.prepareStatement(sql);
// 3.3 给?赋值
ps.setInt(1,id);
// 4 执行sql
ResultSet rs = ps.executeQuery( );
if(rs.next()) {
// 取出数据
String username1 = rs.getString("username");
String password1 = rs.getString("password");
String phone = rs.getString("phone");
Date createTime = rs.getDate("createTime");
double money = rs.getDouble("money");
int sex = rs.getInt("sex");
// 封装数据
user = new User();
user.setId(id);
user.setUsername(username1);
user.setPassword(password1);
user.setPhone(phone);
user.setCreateTime(createTime);
user.setMoney(money);
user.setSex(sex);
}
return user;
}
// 设计方法,查询全部数据,返回值是List集合,集合中是全部用户数据
public static List<User> findAll() throws Exception{
// 1 注册驱动
Class.forName("com.mysql.Driver");
// 2 获得连接
String url = "jdbc:mysql://localhost:3306/java2301?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false";
String username = "root";
String password = "123456";
Connection conn = DriverManager.getConnection(url, username, password);
ArrayList<User> list = new ArrayList<>( );
User user = null;
// 3.1 写sql
String sql = "select * from tb_user";
// 3.2 处理sql
PreparedStatement ps = conn.prepareStatement(sql);
// 4 执行
ResultSet rs = ps.executeQuery( );
while(rs.next()) {
// 取出数据
int id = rs.getInt("id");
String username1 = rs.getString("username");
String password1 = rs.getString("password");
String phone = rs.getString("phone");
Date createTime = rs.getDate("createTime");
double money = rs.getDouble("money");
int sex = rs.getInt("sex");
// 封装数据
user = new User();
user.setId(id);
user.setUsername(username1);
user.setPassword(password1);
user.setPhone(phone);
user.setCreateTime(createTime);
user.setMoney(money);
user.setSex(sex);
// 【重点】 将对象存储入集合
list.add(user);
}
return list;
}
十一、DbUtils【重点,理解,会用】
11.1 介绍
Apache DBUtils是一个流行的数据库工具库,它提供了一组简单、轻量级的工具和接口,用于简化与关系型数据库进行交互的过程。
- ResultSetHandler接口:转换类型接口
BeanHandler类:实现类,把一条记录转换成对象
BeanListHandler类:实现类,把多条记录转换成List集合。
- ScalarHandler类:实现类,适合获取一行一列的数据。
QueryRunner:执行sql语句的类
- 增、删、改:
update()
;- 查询:
query()
;
11.2 依赖
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
11.3 使用
package com.qf.jdbc;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
/**
* --- 天道酬勤 ---
*
* @author QiuShiju
* @desc 使用DbUtils完成crud
*
* 扩展: java实体类,叫做javabean
* bean即对象
*
*/
public class Demo6 {
public static void main(String[] args) throws Exception {
// delete( );
// insert();
// selectOne();
selectAll();
}
private static void delete() throws SQLException {
// 加载驱动不再需要
// 通过驱动管理器获得连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2313?useSSL=false", "root", "123456");
// 创建sql执行器
QueryRunner queryRunner = new QueryRunner( );
/**
* 参数1: 数据库连接对象
* 参数2: sql语句字符串,也需要参数变?
* 参数3: 给?赋值
*/
int i = queryRunner.update(conn, "delete from tb_user where id = ?", 6);
System.out.println(i );
DbUtils.closeQuietly(conn);
}
private static void insert() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
QueryRunner queryRunner = new QueryRunner( );
Object[] params = {6,"zzz","123456","1111",new java.sql.Date(1),1000.0,1};
/**
* update()方法的第三个参数是不定长参数
* 即可以传入任意个数的参数值
* 不定长参数本质上其实是数组
* -----------------------
* 需要注意数组中的值的顺序需要和?的顺序一致
*/
int i = queryRunner.update(conn, "insert into tb_user values (?,?,?,?,?,?,?)", params);
System.out.println(i );
DbUtils.closeQuietly(conn);
}
// 查一个,封装
private static void selectOne() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// sql执行器
QueryRunner queryRunner = new QueryRunner( );
// 查询结果的对象处理器,作用是将查询结果直接封装成指定对象
BeanHandler<User> handler = new BeanHandler<>(User.class);
/**
* 执行查询调用query方法
* 参数1: 数据库连接
* 参数2: sql语句,如果有参数用?
* 参数3: 查询结果封装处理器
* 参数4: 不定长参数,对?赋值
*/
User user = queryRunner.query(conn, "select * from tb_user where id = ?", handler, 1);
System.out.println(user );
DbUtils.closeQuietly(conn);
}
// 查询全部,使用集合存储对象
private static void selectAll() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// sql执行器
QueryRunner queryRunner = new QueryRunner( );
// 查询[多个结果]的对象处理器
BeanListHandler<User> handler = new BeanListHandler<>(User.class);
List<User> list = queryRunner.query(conn, "select * from tb_user", handler);
list.forEach(s -> System.out.println(s ));
DbUtils.closeQuietly(conn);
}
}
Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/java2311?useSSL=false”, “root”, “123456”);
// sql执行器
QueryRunner queryRunner = new QueryRunner( );
// 查询结果的对象处理器,作用是将查询结果直接封装成指定对象
BeanHandler handler = new BeanHandler<>(User.class);
/**
* 执行查询调用query方法
* 参数1: 数据库连接
* 参数2: sql语句,如果有参数用?
* 参数3: 查询结果封装处理器
* 参数4: 不定长参数,对?赋值
*/
User user = queryRunner.query(conn, “select * from tb_user where id = ?”, handler, 1);
System.out.println(user );
DbUtils.closeQuietly(conn);
}
// 查询全部,使用集合存储对象
private static void selectAll() throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/java2311?useSSL=false", "root", "123456");
// sql执行器
QueryRunner queryRunner = new QueryRunner( );
// 查询[多个结果]的对象处理器
BeanListHandler<User> handler = new BeanListHandler<>(User.class);
List<User> list = queryRunner.query(conn, "select * from tb_user", handler);
list.forEach(s -> System.out.println(s ));
DbUtils.closeQuietly(conn);
}
}