day2324_jdbc

今日内容

零、 复习昨日
一、作业
二、SQL注入
三、PreparedStatement
四、事务
五、DBUtil

零、 复习昨日

一、引言


1.1 如何操作数据库

使用客户端工具访问数据库,需要手工建立连接,输入用户名和密码登录,编写 SQL 语句,点击执行,查看操作结果(结果集或受影响行数)。

客户端操作数据库步骤
image-20230316181353316

1.2 实际开发中,会采用客户端操作数据库吗?

在实际开发中,当用户的数据发生改变时,不可能通过客户端操作执行 SQL 语句,因为操作量过大,无法保证效率和正确性。

二、JDBC


2.1 什么是 JDBC?

JDBC(Java Database Connectivity) Java 连接数据库的规范(标准),可以使用 Java 语言连接数据库完成 CRUD 操作。

2.2 JDBC 核心思想

Java 中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver 数据库驱动)。

核心思想
image-20230316181411600

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)
image-20230320105013907
选择libraries,添加jar包
image-20221121111310058
本地磁盘选择jar包
image-20221121111402075
应用生效
image-20221121111442727
下方,External查看导入类库
image-20221121111616446

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: 利用反射技术,将驱动类加载到JVMClass.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 执行sqlint 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();}
}

image-20221121164359945

六、登录案例【重要】

需求:

  • 通过控制台用户输入用户名和密码。
  • 用户输入的用户名和密码作为条件,编写查询 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...
}

image-20221122160619448

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注入是很危险

image-20230322084643699

8.2 避免SQL注入

问题出现在用户输入数据时,里面有关键词,再配合字符串拼接导致出现SQL注入.所以为了避免SQL注入,可以在用户输入数据到SQL之前,先把SQL语句预编译,预处理后,JDBC就会知道此SQL需要几个参数,后续再将用户输入的数据给参数填充.

这就是PreparedStatement

九、PreparedStatement【重点】

PreparedStatement是Statement的子接口,用来预处理SQL语句

PreparedStatement使用

  • 先写SQL语句,SQL语句中的参数不能直接拼接,而是使用?占位
  • 使用ps预处理SQL语句,处理的?号,ps内部就会知道此SQL语句需要几个参数
  • 再动态给?处填充值
  • 执行sql

image-20230322084657336

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 sqlString 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 sqlString 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 先写sqlString 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 执行sqlResultSet 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 写sqlString sql = "select * from tb_user";// 3.2 处理sqlPreparedStatement 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);
}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/143553.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java设计模式-结构型模式-适配器模式

适配器模式 适配器模式应用场景案例类适配器模式对象适配器模式接口适配器模式适配器模式在源码中的使用 适配器模式 如图&#xff1a;国外插座标准和国内不同&#xff0c;要使用国内的充电器&#xff0c;就需要转接插头&#xff0c;转接插头就是起到适配器的作用 适配器模式&…

Ansible playbook详解

playbook是ansible用于配置&#xff0c;部署&#xff0c;和被管理被控节点的剧本 playbook常用的YMAL格式&#xff1a;&#xff08;文件名称以 .yml结尾&#xff09; 1、文件的第一行应该以 "---" (三个连字符)开始&#xff0c;表明YMAL文件的开始。    2、在同一…

C# 将PDF文档转换为Word文档

一.开发框架&#xff1a; .NetCore6.0 工具&#xff1a;Visual Studio 2022 二.思路&#xff1a; 1.使用SHA256Hash标识文档转换记录&#xff0c;数据库已经存在对应散列值&#xff0c;则直接返还已经转换过的文档 2.数据库没有对应散列值记录的话&#xff0c;则保存上传PDF…

OpenHarmony Promise详解

一&#xff0c;定义 作为一个android开发人员&#xff0c;刚接触Promise可能不好理解&#xff0c;因为android中的异步操作都是开启线程操作或者kotlin的协程&#xff0c;但是Promise并不是单独去开启一个线程来处理异步任务&#xff0c;它是在同一个线程中去处理异步任务。异…

性能测试 —— Jmeter分布式测试的注意事项和常见问题

Jmeter是一款开源的性能测试工具&#xff0c;使用Jmeter进行分布式测试时&#xff0c;也需要注意一些细节和问题&#xff0c;否则可能会影响测试结果的准确性和可靠性。 Jmeter分布式测试时需要特别注意的几个方面 1. 参数化文件的位置和内容 如果使用csv文件进行参数化&…

java算法学习索引之动态规划

一 斐波那契数列问题的递归和动态规划 【题目】给定整数N&#xff0c;返回斐波那契数列的第N项。 补充问题 1&#xff1a;给定整数 N&#xff0c;代表台阶数&#xff0c;一次可以跨 2个或者 1个台阶&#xff0c;返回有多少种走法。 【举例】N3&#xff0c;可以三次都跨1个台…

python循环队列

1.循环队列简介&#xff1a; 循环队列是一种队列的实现方式&#xff0c;它可以避免队列空间的浪费。循环队列的特点是队列的末尾连接到队列的开头&#xff0c;形成一个循环。这样当队列尾部元素达到队列的最大容量时&#xff0c;新的元素可以循环地放入队列的开头。这种设计使…

Linux使用Docker完整安装Superset,同时解决please use superset_config.py to override it报错

文章目录 Docker安装Superset流程1. 首先获取镜像2. 生成SSL3. 创建Superset容器4. 更新数据库5. 测试访问Superset Docker安装Superset流程 1. 首先获取镜像 docker pull amancevice/superset2. 生成SSL 接下来我们运行一些额外的程序&#xff1a; openssl rand -base64 4…

ubuntu开机系统出错且无法恢复。请联系系统管理员。

背景&#xff1a; ubuntu22.04.2命令行&#xff0c;执行自动安装系统推荐显卡驱动命令&#xff0c;字体变大&#xff0c;重启后出现如下图错误&#xff0c;无法进入系统&#xff0c;无法通过CTRLALTF1-F3进入TTY模式。 解决办法&#xff1a; 1.首先要想办法进入系统&#xff…

python实现一个简单的桌面倒计时小程序

本章内容主要是利用python制作一个简单的桌面倒计时程序&#xff0c;包含开始、重置 、设置功能。 目录 一、效果演示 二、程序代码 一、效果演示 二、程序代码 #!/usr/bin/python # -*- coding: UTF-8 -*- """ author: Roc-xb """import tkin…

Python数据容器(字典)

字典 1.字典的定义2.字典数据的获取3.字典的嵌套4.嵌套字典的内容获取5.字典的常用操作6.常用操作总结7.遍历字典8.练习 1.字典的定义 同样使用{}&#xff0c;不过存储的元素是一个一个的&#xff1a;键值对&#xff0c;语法如下 # 定义字典字面量 {key:value,key:value,...,…

systemverilog:interface中的modport用法

使用modport可以将interface中的信号分组并指定方向&#xff0c;方向是从modport连接的模块看过来的。简单示例如下&#xff1a; interface cnt_if (input bit clk);logic rstn;logic load_en;logic [3:0] load;logic [7:0] count;modport TEST (input clk, count,output rst…

百度飞浆环境安装

前言&#xff1a; 在安装飞浆环境之前得先把pytorch环境安装好&#xff0c;不过关于pytorch网上教程最多的都是通过Anaconda来安装&#xff0c;但是Anaconda环境安装容易遇到安装超时导致安装失败的问题&#xff0c;本文将叫你如何通过pip安装的方式快速安装&#xff0c;其实这…

一键帮您解决win11最新版画图工具难用问题!

&#x1f984;个人主页:修修修也 ⚙️操作环境:Windows 11 正文 自从win11更新后,新版的画图工具变得非常难用,如: 使用橡皮擦后露出背版马赛克 框住某部分拖动移动时背景露出马赛克剪贴板上图片信息无法直接插入到画图板 目前没有一个好一些的能够在软件内部解决这些问题的方…

【nlp】2.1 认识RNN模型

认识RNN模型 1 什么是RNN模型2 RNN模型的作用3 RNN模型的分类:1 什么是RNN模型 RNN(Recurrent Neural Network),,中文称作循环神经网络,它一般以序列数据为输入, 通过网络内部的结构设计有效捕捉序列之间的关系特征,一般也是以序列形式进行输出。 一般单层神经网络结构:…

8.查询数据

一、单表查询 MySQL从数据表中查询数据的基本语为SELECT语。SELECT语的基本格式是: SELECT {* | <字段列名>} [ FROM <表 1>, <表 2>… [WHERE <表达式> [GROUP BY <group by definition> [HAVING <expression> [{<operator>…

Linux常用的磁盘使用情况命令汇总

1、查看分区使用百分比 df -h 2、查看指定目录磁盘使用情况 du -hac --max-depth1 /opt 参数&#xff1a;-a 查看所有文件&#xff0c;-c 汇总统计&#xff0c;max-depth1 查看深度为1&#xff0c;2级目录不再统计。 3、常用统计命令汇总

【vue实战项目】通用管理系统:api封装、404页

前言 本文为博主的vue实战小项目系列中的第三篇&#xff0c;很适合后端或者才入门的小伙伴看&#xff0c;一个前端项目从0到1的保姆级教学。前面的内容&#xff1a; 【vue实战项目】通用管理系统&#xff1a;登录页-CSDN博客 【vue实战项目】通用管理系统&#xff1a;封装to…

Java绘图-第19章

Java绘图-第19章 1.Java绘图类 1.1Graphics类 Graphics类是用于绘制图形的抽象类&#xff0c;它是java.awt包中的一部分。Graphics类提供了各种方法&#xff0c;可以在图形上绘制各种形状、文本和图像。这些方法包括画线、画矩形、画椭圆、画弧、绘制图像等。 1.2Graphics2…

Oracle(17)Managing Roles

目录 一、基础知识 1、基础介绍 2、Predefined Roles 预定义的角色 3、各种角色的介绍 二、基础操作 1、创建角色 2、修改用户默认role 3、回收role 4、删除role 5、为角色授权 6、授予角色给用户 7、查看用户包含的角色&#xff1a; 8、查看角色所包含的权限 9、…