Mybatis学习-day18
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中数据模型的统称。例如,文件的存储、数据的读取以及对数据表的增删改查等都是数据持久化操作。
MyBatis 支持定制化 SQL、存储过程以及高级映射,可以在实体类和 SQL 语句之间建立映射关系,是一种半自动化的 ORM 实现。其封装性低于 Hibernate,但性能优秀、小巧、简单易学、应用广泛。
MyBatis 的主要思想是将程序中的大量 SQL 语句剥离出来,使用 XML 文件或注解的方式实现 SQL 的灵活配置,将 SQL 语句与程序代码分离,在不修改程序代码的情况下,直接在配置文件中修改 SQL 语句。
MyBatis 与其它持久性框架最大的不同是,MyBatis 强调使用 SQL,而其它框架(例如 Hibernate)通常使用自定义查询语言,即 HQL(Hibernate查询语言)或 EJB QL(Enterprise JavaBeans查询语言)
1. ORM
ORM(Object Relational Mapping,对象关系映射)是一种数据持久化技术,它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过 JavaBean 对象去操作数据库表中的数据。
2. 搭建Mybatis
添加Maven依赖
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.14</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
</dependencies>
在项目的resource的文件夹下创建application.yml,配置mybatis数据源
#配置mybatis的数据源 DataSource
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/easydata
创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EasySpringApplication {
public static void main(String[] args) {
SpringApplication.run(EasySpringApplication.class, args);
}
}
如果启动项目成功,则搭建成功
3. 增删改的实现
在 Spring Boot 配置文件(如 application.properties 或 application.yml)中,mybatis.mapper-locations 设置指定了 MyBatis 映射器(Mapper)XML 文件的位置。这些 XML 文件包含了 SQL 映射语句,通常用于定义 SQL 查询、插入、更新和删除操作。这个配置项告诉 MyBatis 在哪里查找这些映射文件。
具体来说,mybatis.mapper-locations=classpath:mapper/*.xml 这段代码的含义如下:
-
classpath::表示 MyBatis 应该在 Java 类路径(classpath)上搜索映射文件。类路径是 Java 应用程序在运行时查找类文件和资源的位置集合。
-
mapper/:是放置 MyBatis 映射器 XML 文件的目录。这个目录通常位于项目的资源(resources)目录下。例如,在 Maven 或 Gradle 项目中,它通常位于 src/main/resources/mapper。
-
*.xml:是一个通配符,表示 MyBatis 应该加载 mapper 目录下的所有 .xml 文件。每个 XML 文件通常对应于一个映射器接口(Mapper Interface),其中包含了 SQL 语句和对应的方法。
这种配置方式使得 MyBatis 可以自动找到并加载这些映射文件,进而将 XML 文件中定义的 SQL 语句关联到对应的映射器接口。这样,当在应用程序中调用映射器接口的方法时,MyBatis 会执行相应的 SQL 语句。
mybatis:
mapper-locations: classpath:mapper/*.xml
要操作的数据库表结构如下图所示
在resource目录下新建mapper文件夹,在mapper文件夹中创建Staff_Mapper.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.easy.dao.IStaffDao">
<!--在这里写SQL语句-->
<select id="getNow" resultType="string">
select now()
</select>
<insert id="addStaff">
/*预编译*/
insert into staff(code, name, salary, username, userpass)
value(#{code}, #{name}, #{salary}, #{username}, #{userpass})
</insert>
<delete id="delStaff">
delete from staff where id = #{id}
</delete>
<update id="editStaff">
update staff set name = #{name}, salary = #{salary}, username = #{username}, userpass = #{userpass}
where id = #{id}
</update>
</mapper>
创建bean类Staff
package com.easy.bean;
import java.math.BigDecimal;
public class Staff {
private int id;
private String code;
private String name;
private BigDecimal salary;
private String username;
private String userpass;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BigDecimal getSalary() {
return salary;
}
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpass() {
return userpass;
}
public void setUserpass(String userpass) {
this.userpass = userpass;
}
}
创建Mapper接口IStaff
@Mapper注解是由Mybatis框架中定义的一个描述数据层接口的注解,注解往往起到的都是一个描述性作用,用于告诉Spring框架此接口的实现类由Mybatis负责创建,并将其实现类对象存储到spring容器中。
import com.easy.bean.Staff;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface IStaffDao {
String getNow();
//sql语句没有返回值 方法有返回值,为插入的行数
int addStaff(Staff staff);
int delStaff(int id);
int editStaff(Staff staff);
}
在控制类中注入接口类,调用Mybatis实现的方法
@RestController
public class EasyController {
@Autowired
IStaffDao dao;
@GetMapping("now")
public String now(){
return dao.getNow();
}
@PostMapping("staff")
public String addStaff(Staff staff){
int res = dao.addStaff(staff);
return res + " add successfully!";
}
@DeleteMapping("staff/{id}")
public String delStaff(@PathVariable int id){
int res = dao.delStaff(id);
return res + " delete successfully";
}
@PutMapping("staff")
public String editStaff(Staff staff){
int res = dao.editStaff(staff);
return res + " edit successfully";
}
}
启动项目,使用ApiPost发送不同的请求,进行测试
测试成功
4. 预编译(#) 参数拼接($)
在mybatis中,#和$分别代表预编译参数和字符串拼接。它们在处理SQL语句中的参数时有着不同的行为
4.1 预编译(#)
1、作用:#用于表示预编译参数,它可以防止SQL注入攻击。当使用#时,MyBatis会将参数值进行转义处理,确保参数值不会被当作SQL代码执行。
2、语法:在SQL语句中,使用#{}包围参数名称,如:SELECT * FROM users WHERE id = #{id}
。
3.示例
<select id="getUser" parameterType="int" resultType="com.example.User">
SELECT * FROM users WHERE id = #{id}
</select>
4、特点:使用#可以确保SQL代码的安全性,防止sql注入和加快批处理的效率,但可能会影响性能。因为预编译参数需要对每个参数值进行转义处理,所以在处理大量参数时可能会导致性能下降。
4.2 参数拼接($)
1、作用:用于表示字符串拼接,它可以将参数值直接插入到sql语句中。当使用用于表示字符串拼接,它可以将参数值直接插入到SQL语句中。当使用时,MyBatis不会对参数值进行转义处理,因此需要注意防止SQL注入攻击。
2、语法:在SQL语句中,使用包围参数名称,如:SELECT * FROM users WHERE name = ${name}
。
3.示例
<select id="getUser" parameterType="string" resultType="com.example.User">
SELECT * FROM users WHERE name = ${name}
</select>
4、特点:使用$可以直接将参数值插入到SQL语句中,可以提高性能。但由于没有进行转义处理,需要注意防止SQL注入攻击。在使用时,应确保参数值是可信的,或对参数值进行手动转义处理。
5. SQL注入
SQL注入(SQL Injection)是一种常见的Web安全漏洞,形成的主要原因是web应用程序在接收相关数据参数时未做好过滤,将其直接带入到数据库中查询,导致攻击者可以拼接执行构造的SQL语句。
当我们使用参数拼接的方式来写sql语句,如下所示
SELECT * FROM users WHERE id = '${id}' LIMIT 0,1;
如果用户传入的参数为1则可以正常查询
SELECT * FROM users WHERE id = '1' LIMIT 0,1;
但若用户多输入了一个单引号,程序就会报错,原因是用户输入的单引号和前面的单引号形成了组合,由此多出了一个单引号导致程序异常
SELECT * FROM users WHERE id = '1''LIMIT 0,1;
既然用户想拼接什么就拼接什么,那么如果用户输入1' or 1 = 1 --
在1后面输入单引号与前面的单引号实现拼接,再在后面加上true的条件,最后将后面的限制给注释掉,用户就能得到所有的users表数据,这就是sql注入。
户传入的参数为1则可以正常查询
SELECT * FROM users WHERE id = '1' LIMIT 0,1;
但若用户多输入了一个单引号,程序就会报错,原因是用户输入的单引号和前面的单引号形成了组合,由此多出了一个单引号导致程序异常
SELECT * FROM users WHERE id = '1''LIMIT 0,1;
既然用户想拼接什么就拼接什么,那么如果用户输入1' or 1 = 1 --
在1后面输入单引号与前面的单引号实现拼接,再在后面加上true的条件,最后将后面的限制给注释掉,用户就能得到所有的users表数据,这就是sql注入。