Java阶段二Day12

news/2025/1/14 20:55:00/

Java阶段二Day12

文章目录

  • Java阶段二Day12
    • JDBC
      • 核心接口
      • JDBC连接的基本流程
      • 实现DDL
      • 实现DML
      • 实现DQL
      • PreparedStatement
    • V20
      • DBUtil
      • UserController
    • 连接池

JDBC

JDBC Java数据库连接 Java Database Connectivity,是java官方提供的一套结构,用于连接DBMS并进行相关操作

核心接口

  • Connection: 表示数据库连接
  • Statement: 用来执行SQL语句的语句对象
  • PreparedStatement: 用来执行预编译SQL语句的语句对象用来表示查询结果集
  • ResultSet: 用来表示查询结构集

JDBC连接的基本流程

  1. 加载驱动
  2. 通过DriverManager 与 DBMS 建立连接 获得 Connection对象
  3. 通过连接对象创建语句对象 Statement
  4. 通过语句对象 执行相应的 SQL语句给数据库
  5. 获得执行SQL的结果

实现DDL

public static void main(String[] args) {/*JDBC提供了连接,操作数据的流程,步骤大致如下:1:加载驱动2:通过DriverManager与DBMS建立连接(返回一个Connection)3:通过连接对象创建语句对象Statement4:通过语句对象执行相应的SQL语句给数据库5:获得执行SQL的结果*/try {//不同的数据库Driver的内容不同//1加载驱动Class.forName("com.mysql.cj.jdbc.Driver");//mysql的驱动//2与数据库建立连接Connection connection = DriverManager.getConnection(//url格式是固定的   数据库地址     /数据库名?参数"jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true","root","root");System.out.println("与数据库建立连接!");//通过连接对象创建用于执行SQL语句的语句对象Statement statement = connection.createStatement();//执行DDL语句String sql = "CREATE TABLE userinfo( " +"  id INT PRIMARY KEY AUTO_INCREMENT, " +"  username VARCHAR(30), " +"  password VARCHAR(30), " +"  nickname VARCHAR(30), " +"  age INT(3)" +")";/*Statement提供了多种执行SQL的方法boolean execute(String sql)用于向数据库执行SQL语句。该方法可以执行任何种类的SQL但是实际上执行DML,DQL都有专门的方法,因此该execute通常只用来执行DDL该方法返回一个boolean值,执行该SQL后是否产生了查询结果集。*/statement.execute(sql);//执行该SQL语句connection.close();System.out.println("表创建成功");} catch (ClassNotFoundException | SQLException e) {e.printStackTrace();}
}

实现DML

public static void main(String[] args) {try {Class.forName("com.mysql.cj.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true","root","root");Statement statement = connection.createStatement();//向userinfo表中插入一条记录/*INSERT INTO userinfo (username,password,nickname,age)VALUES('张三','123456','阿三',22)*///            String sql = "INSERT INTO userinfo (username,password,nickname,age) " +//                         "VALUES('张三','123456','阿三',22)";Scanner scanner = new Scanner(System.in);System.out.println("欢迎注册");System.out.println("请输入用户名");String username = scanner.nextLine();System.out.println("请输入密码");String password = scanner.nextLine();System.out.println("请输入昵称");String nickname = scanner.nextLine();System.out.println("请输入年龄");int age = scanner.nextInt();String sql = "INSERT INTO userinfo (username,password,nickname,age) " +"VALUES('"+username+"','"+password+"','"+nickname+"',"+age+")";/*Statement提供的方法:int executeUpdate(String sql)专门用于执行DML语句的,返回值表达执行该DML后影响了表中多少条记录*/int num = statement.executeUpdate(sql);if(num>0){//至少执行后影响了表中1条记录System.out.println("插入成功");}else{System.out.println("插入失败");}connection.close();} catch (Exception e) {e.printStackTrace();}
}
public static void main(String[] args) {//修改某个用户的密码try {Class.forName("com.mysql.cj.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true","root","root");Statement statement = connection.createStatement();/*UPDATE userinfoSET password='666666'WHERE username='张三'*/String sql = "UPDATE userinfo " +"SET password='666666' " +"WHERE username='张三'";int num = statement.executeUpdate(sql);if(num>0){System.out.println("修改成功");}else{System.out.println("修改失败");}connection.close();} catch (Exception e) {e.printStackTrace();}}

实现DQL

DBUtil

/*** 用来管理数据库链接的类*/
public class DBUtil {static{try {Class.forName("com.mysql.cj.jdbc.Driver");//加载驱动} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException {return DriverManager.getConnection("jdbc:mysql://localhost:3306/tedu?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true","root","root");}
}
public static void main(String[] args) {try (Connection connection = DBUtil.getConnection();){Statement statement = connection.createStatement();/*查看所有老师的id,名字,工资,职称SELECT id,name,salary,titleFROM teacher*/String sql = "SELECT id,name,salary,title " +"FROM teacher ";ResultSet resultSet = statement.executeQuery(sql);/*ResultSet重要方法:boolean next()让结果集向下移动一行,返回值表示是否存在下一行。如果存在下一行则返回true否则返回false。*/while(resultSet.next()){//结果集向下移动一行,并判断改行是否存在//获取该条记录中id字段的值(id字段在数据库中是整数类型)int id = resultSet.getInt("id");//获取该条记录中老师的名字(name字段在数据库中是字符串类型)String name = resultSet.getString("name");//获取工资int salary = resultSet.getInt("salary");//获取职称String title = resultSet.getString("title");System.out.println(id+","+name+","+salary+","+title);}} catch (SQLException e) {e.printStackTrace();}
}

PreparedStatement

使用Statement,拼接SQL语句会导致导致语义发生改变,即 SQL注入攻击,常见的如用户登录验证时在密码一栏填写:a' OR '1'='1

为防止SQL注入采用PreparedStatement替代Statement,实现预编译SQL

预编译SQL:可以先将SQL语句发送给数据库,让数据库生成执行计划理解该SQL的执行意图。然后SQL中需要的数据可以在需要执行该SQL时单独传给数据库。此时数据库仅会将传入的内容当作值看待,而不会因为拼接SQL导致语义发生改变,避免SQL注入攻击问题。

public static void main(String[] args) {/*预编译SQL语句的写法,将原本需要拼接的"值"先用"?"代替SELECT id,username,password,nickname,ageFROM userinfoWHERE username='拼接' AND password='拼接'预编译SQL:SELECT id,username,password,nickname,ageFROM userinfoWHERE username=? AND password=?*/String sql = "SELECT id,username,password,nickname,age " +"FROM userinfo " +"WHERE username=? AND password=?";try (Connection connection = DBUtil.getConnection();){//创建预编译SQL语句执行对象时要先将预编译SQL发送给数据库要求其理解语义PreparedStatement ps = connection.prepareStatement(sql);//执行该sql前要指明预编译SQL中"?"的值是什么/*?是什么类型的值,这里就应当调用对应的set方法例如?表示整数时,调用ps.setInt(...)?表示字符串时,调用ps.setString(...)方法第一个参数表示预编译SQL中第几个"?"."?"从左往右,从上往下,并且"?"从1开始,1表示第一个"?"。*/ps.setString(1,"张三");//第一个?值ps.setString(2,"123456");//第二个?值//将值传给数据库执行该SQLResultSet rs = ps.executeQuery();if(rs.next()){String nickname = rs.getString("nickname");System.out.println("登录成功,欢迎你:"+nickname);}else{System.out.println("登录失败,用户名或密码不正确");}} catch (SQLException throwables) {throwables.printStackTrace();}
}

V20

此版本成功和后台数据库连接

DBUtil

package com.birdboot.util;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBUtil {static {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (ClassNotFoundException e) {e.printStackTrace();}}public static Connection getConnection() throws SQLException {return DriverManager.getConnection("jdbc:mysql://localhost:3307/birdbootdb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true","root", "root");}
}

UserController

package com.birdboot.controller;import com.birdboot.annotations.Controller;
import com.birdboot.annotations.RequestMapping;
import com.birdboot.http.HttpServletRequest;
import com.birdboot.http.HttpServletResponse;
import com.birdboot.util.DBUtil;
import entity.User;import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;/*** 处理与用户相关的业务*/
@Controller
public class UserController {private static File userDir;static {userDir = new File("./users");if (!userDir.exists()) {userDir.mkdirs();}}@RequestMapping("/regUser")public void reg(HttpServletRequest req, HttpServletResponse resp) {System.out.println("开始处理用户注册");String username = req.getParameter("username");String password = req.getParameter("password");String nickname = req.getParameter("nickname");String ageStr = req.getParameter("age");if (username == null || username.isEmpty() || password == null || password.isEmpty()|| nickname == null || nickname.isEmpty() || ageStr == null || ageStr.isEmpty()|| !ageStr.matches("[0-9]+")) {resp.sendRedirect("/reg_info_error.html");return;}int age = Integer.parseInt(ageStr);//查看是否为重复用户try (Connection conn = DBUtil.getConnection()){String sql = "SELECT 1 FROM userinfo WHERE username = ?";PreparedStatement ps1 = conn.prepareStatement(sql);ps1.setString(1,username);ResultSet rs = ps1.executeQuery();if (rs.next()){resp.sendRedirect("/have_user.html");}else {String sql2 = "INSERT INTO userinfo(username,password,nickname,age) " +"VALUES(?,?,?,?)";PreparedStatement ps2 = conn.prepareStatement(sql2);ps2.setString(1,username);ps2.setString(2,password);ps2.setString(3,nickname);ps2.setInt(4,age);int num = ps2.executeUpdate();if (num > 0){resp.sendRedirect("/reg_success.html");}}} catch (SQLException e) {e.printStackTrace();}}@RequestMapping("/loginUser")public void login(HttpServletRequest req, HttpServletResponse resp) {System.out.println("开始处理用户登录!!!");String username = req.getParameter("userName");String password = req.getParameter("password");if (username == null || username.isEmpty() || password == null || password.isEmpty()) {resp.sendRedirect("/login_info_error.html");return;}try (Connection conn = DBUtil.getConnection();){String sql = "SELECT username,password,nickname,age FROM userinfo " +"WHERE username = ? AND password = ?";PreparedStatement ps = conn.prepareStatement(sql);ps.setString(1, username);ps.setString(2,password);ResultSet rs = ps.executeQuery();if (rs.next()){//后期开发,将用户信息保存到 sessionresp.sendRedirect("login_success.html");}else {resp.sendRedirect("login_fail.html");}} catch (SQLException e) {e.printStackTrace();}}
}

连接池

与线程池同样道理。都是池化思想,重用内容和控制数量

学习使用阿里的DruidDataSource

maven设置:

<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.21</version>
</dependency>
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version>
</dependency>

DBUtil

package com.birdboot.util;import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBUtil {//连接池private static DruidDataSource ds;static {initDruidDataSource();}private static void initDruidDataSource() {ds = new DruidDataSource();ds.setUsername("root");ds.setPassword("root");ds.setUrl("jdbc:mysql://localhost:3307/birdbootdb?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true");//最大连接数ds.setMaxActive(30);//初始连接数ds.setInitialSize(5);}public static Connection getConnection() throws SQLException {return ds.getConnection();}
}

http://www.ppmy.cn/news/54405.html

相关文章

结构体指针、数组指针和结构体数组指针

结构体指针 首先让我们定义结构体&#xff1a; struct stu { char name[20]; long number; float score[4]; }; 再定义指向结构体类型变量的指针变量&#xff1a; struct stu *student; /*定义结构体类型指针*/ student malloc(sizeof(struct stu)); /*为指针变量分…

8个免费的PNG素材网站推荐

很多设计小白都不知道什么是PNG。事实上&#xff0c;PNG是一种支持透明度的图像格式。当你想在设计中将图像与背景或文本混合时&#xff0c;它就会派上用场。 如果你没有时间为你正在处理的设计创建透明的PNG图像&#xff0c;你也可以使用我收集的PNG素材网站&#xff0c;以便…

【Vue 基础】vue-cli初始化项目及相关说明

目录 1. 创建项目 2. 项目文件介绍 3. 项目的其它配置 3.1 项目运行时&#xff0c;让浏览器自动打开 3.2 关闭eslint校验功能 3.3 src文件夹简写方法 1. 创建项目 vue create 项目名 2. 项目文件介绍 创建好的项目中包含如下文件&#xff1a; &#xff08;1&#xff09…

电梯导航栏的实现

点击跳到指定位置类似于电梯导航 .w {width: 1200px;margin: 0 auto; } .fixedtool {position: fixed;top: 100px;left: 50%;margin-left: -676px;width: 66px;background-color: #fff;display: none; }.fixedtool li {height: 32px;line-height: 32px;text-align: center;fo…

03_Uboot网络命令与MMC和文件操作命令

目录 网络操作命令 ping命令 nfs 命令 tftp 命令 EMMC和SD卡操作命令 mmc info命令 mmc rescan命令 mmc list 命令 mmc dev 命令 mmc part命令 mmc read 命令 mmc write 命令 mmc erase 命令 FAT 格式文件系统操作命令 fatinfo 命令 fatls 命令 fstype 命令 …

【前端面经】JS-深浅拷贝

理解深浅拷贝 深浅拷贝问题的出现是由于JavaScript对不同类型的存储方式而引发的。 对于原始数据类型&#xff0c;它们的值是直接存储在栈内存中&#xff1b; 而复杂数据类型&#xff0c;则在栈内存中记录它的指针&#xff0c;而指针指向堆内存中真正的值。 所以对于原始数据类…

2023/4/25总结

刷题&#xff1a; 第一周任务 - Virtual Judge (vjudge.net) 1.这一题的思路就是先排除前面和后面相等的&#xff0c;然后找到不等的情况&#xff0c;不等情况的下标开始前后都走&#xff0c;看看是不是和b数组构成了一个升序数组即可。 #include<stdio.h> #define Ma…

合合信息新推出反光消除技术,助力手写文字识别更精准

近期&#xff0c;合合信息旗下扫描全能王推出液晶手写板&#xff08;简称“手写板”&#xff09;&#xff0c;为用户带来仿真、流畅的书写绘画体验&#xff0c;一同发布的还有扫描全能王APP的新功能“拍手写板”。该功能可帮助用户在拍摄手写板内容后去除图片上的反光干扰&…