AI+JavaWeb(四)MySQL+JDBC+MyBatis
MySQL+JDBC+MyBatis
MySQL
图形化工具:DataGrip
DataGrip是JetBrains旗下的一款数据库管理工具,是管理和开发MySQL、Oracle、PostgreSQL的理想解决方案。
DataGrip这款工具可以不用安装,因为Jetbrains公司已经将DataGrip这款工具的功能已经集成到了IDEA当中,所以我们就可以使用IDEA来作为一款图形化界面工具来操作Mysql数据库。
JDBC
Java DataBase Connectivity:Java语言操作关系型数据库的一套API。

入门程序
基本流程:
- 注册jdbc驱动
- 获取数据库连接
- 获取SQL语句执行对象(句柄)
- 通过句柄执行SQL语句
- 释放资源

如何查找MySQL的jdbc驱动类名?

package com.zjq;
import org.junit.jupiter.api.Test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcTest {
/*
JDBC入门程序
*/
@Test
public void testUpdate() throws ClassNotFoundException, SQLException {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
String url = "jdbc:mysql://localhost:3306/web01";//格式:协议名:数据库://地址:端口/数据库名
String username = "root",password = "zjq.182";
Connection conn = DriverManager.getConnection(url, username, password);
//3.获取SQL语句执行对象
Statement statement = conn.createStatement();
//4.执行SQL
int cnt = statement.executeUpdate("update user set age = 18 where id = 1");//DML
System.out.println("SQL更新语句影响的记录数:" + cnt);
//5.释放资源
statement.close();
conn.close();
}
}
查询数据DQL

基本流程:
- 注册jdbc驱动
- 获取数据库连接
- 获取预编译查询语句的对象(句柄)并执行SQL语句
- 处理查询结果集
- 释放资源
@Test
public void testSelect() throws ClassNotFoundException, SQLException {
// 1.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");
//2.获取数据库连接
String url = "jdbc:mysql://localhost:3306/web01";//格式:协议名:数据库://地址:端口/数据库名
String username = "root",password = "zjq.182";
Connection conn = DriverManager.getConnection(url, username, password);
PreparedStatement stmt = null;
ResultSet rs = null;
try{
//3.获取SQL语句执行对象并执行SQL
String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
stmt = conn.prepareStatement(sql);
stmt.setString(1,"zjq");//注意:下标从1开始
stmt.setString(2,"123456");
//4.处理查询结果
rs = stmt.executeQuery();
while(rs.next()){
User user = new User(
rs.getInt("id"),
rs.getString("username"),
rs.getString("password"),
rs.getString("name"),
rs.getInt("age")
);
System.out.println(user);
}
}catch (SQLException exception){
exception.printStackTrace();
}finally {
//5.释放资源
rs.close();
stmt.close();
conn.close();
}
}
预编译SQL
- 静态SQL(参数硬编码)
Statement statement = conn.createStatement();
int cnt = statement.executeUpdate("update user set age = 18 where id = 1");//DML
System.out.println("SQL更新语句影响的记录数:" + cnt);
- 预编译SQL(参数动态传递)
String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
PrepareStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1,"zjq");//注意:下标从1开始
pstmt.setString(2,"123456");
ResultSet rs = pstmt.executeQuery();
注意:表名、字段名不可作为预编译的参数值,因为它们是SQL语法结构的一部分。
优势
- 可以防止SQL注入,更加安全
SQL注入:通过控制输入来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。
例如:
String sql = "SELECT * FROM user WHERE username = '" + input_name + "' AND password = '" + input_pwd + "'";
上面程序中,当输入的password为' or '1'='1时,整个SQL语句变为SELECT * FROM user WHERE username = 'ferwf' AND password = '' or '1'='1',WHERE始终为TRUE,使得无须输入正确的账密即可登录成功。
2. 性能更高

MyBatis
MyBatis是一款优秀的持久层框架,主要用于简化JDBC的开发,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。官方文档:https://mybatis.org/mybatis-3/zh_CN/index.html


入门程序

基本流程:
- 创建SpringBoot模块,引入Spring Web、Lombok、Mybatis、MySQL Driver等依赖项

- 准备数据库表User和实体类User
package org.zjq.springboot_mybatis_01.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
private String name;
private Integer age;
}
- 配置MyBatis(在application.properties中p配置数据库连接信息)
注意:需要将.properties属性文件的默认编码设置为UTF-8

spring.application.name=springboot_mybatis_01
# 配置数据库连接信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/web01
spring.datasource.username=root
spring.datasource.password=zjq.182
- 编写MyBatis的持久层接口
UserMapper.java
package org.zjq.springboot_mybatis_01.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.zjq.springboot_mybatis_01.pojo.User;
import java.util.List;
@Mapper //运行时,会自动为该接口创建一个类对象(代理对象),且会自动将该实现类对象存入SpringBoot的IOC容器
public interface UserMapper {
@Select("select * from user")
public List<User> findAll();
}
- 编写springboot单元测试方法
package org.zjq.springboot_mybatis_01;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.zjq.springboot_mybatis_01.mapper.UserMapper;
import org.zjq.springboot_mybatis_01.pojo.User;
import java.util.List;
@SpringBootTest //SpringBoot单元测试的注解 - 会在单元测试运行时,加载springboot的环境-IOC容器
class SpringbootMybatis01ApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void findAllTest(){
List<User> users = userMapper.findAll();
users.forEach(System.out::println);
}
}
IDE辅助配置
idea辅助SQL语句编写的配置
默认在MyBatis中配的SQL语句是不识别的,可做如下配置:

idea配置MyBatis的日志输出
默认情况下,在Mybatis中执行SQL语句时,看不到执行日志。可在applications.properties配置文件中加入如下配置,即可查看日志:
# Mybatis的配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

JDBC vs Mybatis

数据库连接池
数据库连接池是一个容器,负责分配、管理数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立。
当某个连接的空闲时间超过最大空闲时间,连接池会对其释放,从而避免由于没有释放连接而引起的数据库连接泄漏。

优势:
- 资源复用
- 提升系统响应速度(避免重复建立连接)
- 避免数据库连接遗漏
标准接口:DataSource
官方提供的数据库连接池接口,由第三方组织实现此接口
功能:通过Connection getConnection() throws SQLException获取连接
常见产品

Hikari:Springboot默认提供的连接池
Druid:阿里巴巴开源的数据库连接池项目,是Java最好的数据库连接池之一
切换数据库连接池
由Hikari切换为Druid
pom.xml
<!--Druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.19</version>
</dependency>
application.properties
# 选择Druid作为数据库连接池的实现
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
增删改查操作
MyBatis SQL中的#号和$号

注意:表名、字段名不可作为预编译的参数值,因为它们是SQL语法结构的一部分。如需动态设置,只能使用拼接符$。
SQL注入示例
UserMapper.java
@Mapper //运行时,会自动为该接口创建一个类对象(代理对象),且会自动将该实现类对象存入SpringBoot的IOC容器
public interface UserMapper {
@Select("select * from user where username = #{username} AND password = #{pwd}")
public List<User> safe_login(String username,String pwd);
@Select("select * from user where username = ${username} AND password = ${pwd}")
public List<User> unsafe_login(String username,String pwd);
}
Test.java
@ParameterizedTest
@CsvSource({
"\"zjq\",\"\" OR '1'='1'",
})
public void loginTest(String username,String pwd){
List<User> users = userMapper.unsafe_login(username,pwd);
Assertions.assertEquals(0, users.size());
}
删除
示例:根据id删除用户信息
@Delete("delete from user where id = #{id}")
public Integer deleteById(Integer id);
返回值为Integer时表示:执行SQL语句影响的记录个数,即删除的记录个数,也可以为void
新增
示例:新增一个用户
@Insert("insert into user (username, password, name, age) values (#{username},#{password},#{name},#{age});")
public Integer Insert(User user);
返回值为Integer时表示:执行SQL语句影响的记录个数,即成功新增的记录个数,也可以为void
更新
示例:根据ID更新用户信息
/*
更新用户的所有信息
*/
@Update("update user set username=#{username},password=#{password},name=#{name},age=#{age} where id=#{id}")
public Integer Update(User user);
/*
更新用户的单个字段信息
*/
@Update("update user set name=#{name} where id=#{id}")
public Integer Updatename(User user);
返回值为Integer时表示:执行SQL语句影响的记录个数,即被更新的记录个数,也可以为void
查询
示例:根据用户名和密码查询用户信息
@Select("select * from user where username = #{username} AND password = #{pwd}")
public User safe_login(@Param("username") String username,@Param("pwd") String pwd);
@Select("select * from user where username = ${username} AND password = ${pwd}")
public User unsafe_login(@Param("username") String username,@Param("pwd") String pwd);
注意:
- 基于官方骨架创建的Springboot项目中,接口编译时会保留方法形参名,@Param注解可以省略。
- 返回值可以自定义,对于登录模块最多返回一条记录时,可定义返回值为
User,当查询不到时返回null。
XML映射配置
在Mybatis中,既可以通过注解配置SQL语句,也可以通过XML配置文件来配置SQL语句。
默认规则
- XML映射文件的名称与Mapper接口名称一致,且将XML映射文件和Mapper接口放置在相同包下(同名同包)
注意:Resource中定义多层目录是通过/来进行的,不能使用.。

- XML映射文件的namespace属性为Mapper接口全限定名
- XML映射文件中SQL语句的id与Mapper接口中的方法名一致,且返回类型一致,返回类型为单行查询结果的封装bean

示例
将UserMapper中的方法使用XML映射配置文件改造
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.zjq.springboot_mybatis_01.mapper.UserMapper">
<!-- 注意:只有select类型语句有返回值,且返回值类型为单行查询记录的封装bean-->
<select id="findAll" resultType="org.zjq.springboot_mybatis_01.pojo.User">
select * from user
</select>
<select id="findByName" resultType="org.zjq.springboot_mybatis_01.pojo.User">
select * from user where name = #{name}
</select>
<select id="safe_login" resultType="org.zjq.springboot_mybatis_01.pojo.User">
select * from user where username = #{username} AND password = #{pwd}
</select>
<select id="unsafe_login" resultType="org.zjq.springboot_mybatis_01.pojo.User">
select * from user where username = ${username} AND password = ${pwd}
</select>
<delete id="deleteById">
delete from user where id = #{id}
</delete>
<insert id="Insert">
insert into user (username, password, name, age) values (#{username},#{password},#{name},#{age});
</insert>
<update id="Update">
update user set username=#{username},password=#{password},name=#{name},age=#{age} where id=#{id}
</update>
<update id="Updatename">
update user set name=#{name} where id=#{id}
</update>
</mapper>
UserMapper.java
package org.zjq.springboot_mybatis_01.mapper;
import org.apache.ibatis.annotations.*;
import org.zjq.springboot_mybatis_01.pojo.User;
import java.util.List;
@Mapper //运行时,会自动为该接口创建一个类对象(代理对象),且会自动将该实现类对象存入SpringBoot的IOC容器
public interface UserMapper {
// @Select("select * from user")
public List<User> findAll();
// @Select("select * from user where name = #{name}")
public List<User> findByName(String name);
// @Select("select * from user where username = #{username} AND password = #{pwd}")
public User safe_login(@Param("username") String username,@Param("pwd") String pwd);
// @Select("select * from user where username = ${username} AND password = ${pwd}")
public User unsafe_login(@Param("username") String username,@Param("pwd") String pwd);
// @Delete("delete from user where id = #{id}")
public Integer deleteById(Integer id);
// @Insert("insert into user (username, password, name, age) values (#{username},#{password},#{name},#{age});")
public Integer Insert(User user);
/*
更新用户的所有信息
*/
// @Update("update user set username=#{username},password=#{password},name=#{name},age=#{age} where id=#{id}")
public Integer Update(User user);
/*
更新用户的单个字段信息
*/
// @Update("update user set name=#{name} where id=#{id}")
public Integer Updatename(User user);
}
辅助配置
指定XML配置文件的位置
当XML配置文件与Mapper接口文件不在同一个包中,可通过在application.properties文件中指定XML文件的路径。

# 指定mybatis的XML映射配置文件的位置
# main中的java和resources目录下的文件编译后都会放在target的classes目录中,因此用classpath表示classes目录的路径
mybatis.mapper-locations=classpath:mapper/*.xml
IDEA中MybatisX插件
MybatisX是一款基于IDEA的快速开发Mybatis的插件,为效率而生。
MybatisX plugin Features:
mapper and xml can jump back and forth
mybatis.xml,mapper.xml prompt
mapper and xml support auto prompt like jpa (reference MybatisCodeHelperPro)
integrate mybatis generator Gui (copy from free mybatis plugin)

浙公网安备 33010602011771号