Java阶段二Day12
JDBC
JDBC Java数据库连接 Java Database Connectivity
,是java官方提供的一套结构,用于连接DBMS并进行相关操作
核心接口
- Connection: 表示数据库连接
- Statement: 用来执行SQL语句的语句对象
- PreparedStatement: 用来执行预编译SQL语句的语句对象用来表示查询结果集
- ResultSet: 用来表示查询结构集
JDBC连接的基本流程
- 加载驱动
- 通过DriverManager 与 DBMS 建立连接 获得 Connection对象
- 通过连接对象创建语句对象 Statement
- 通过语句对象 执行相应的 SQL语句给数据库
- 获得执行SQL的结果
实现DDL
public static void main(String[] args) {
/*
JDBC提供了连接,操作数据的流程,步骤大致如下:
1:加载驱动
2:通过DriverManager与DBMS建立连接(返回一个Connection)
3:通过连接对象创建语句对象Statement
4:通过语句对象执行相应的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 userinfo
SET 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,title
FROM 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,age
FROM userinfo
WHERE username='拼接' AND password='拼接'
预编译SQL:
SELECT id,username,password,nickname,age
FROM userinfo
WHERE 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");//第二个?值
//将值传给数据库执行该SQL
ResultSet 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()){
//后期开发,将用户信息保存到 session
resp.sendRedirect("login_success.html");
}else {
resp.sendRedirect("login_fail.html");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
连接池
与线程池同样道理。都是池化思想,重用内容和控制数量
学习使用阿里的DruidDataSource
maven设置:文章来源:https://www.toymoban.com/news/detail-429464.html
<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文章来源地址https://www.toymoban.com/news/detail-429464.html
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();
}
}
到了这里,关于Java阶段二Day12的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!