引言
数据持久化是将内存中的数据模型转换为存储模型,以及将存储模型转换为内存中数据模型的统称。例如,文件的存储、数据的读取以及对数据表的增删改查等都是数据持久化操作。
MyBatis 支持定制化 SQL、存储过程以及高级映射,可以在实体类和 SQL 语句之间建立映射关系,是一种半自动化的 ORM 实现。其封装性低于 Hibernate,但性能优秀、小巧、简单易学、应用广泛。
ORM(Object Relational Mapping,对象关系映射)是一种数据持久化技术,它在对象模型和关系型数据库之间建立起对应关系,并且提供了一种机制,通过 JavaBean 对象去操作数据库表中的数据。
MyBatis 前身为 IBatis,2002 年由 Clinton Begin 发布。2010 年从 Apache 迁移到 Google,并改名为 MyBatis,2013 年又迁移到了 Github。
MyBatis 的主要思想是将程序中的大量 SQL 语句剥离出来,使用 XML 文件或注解的方式实现 SQL 的灵活配置,将 SQL 语句与程序代码分离,在不修改程序代码的情况下,直接在配置文件中修改 SQL 语句。
MyBatis 与其它持久性框架最大的不同是,MyBatis 强调使用 SQL,而其它框架(例如 Hibernate)通常使用自定义查询语言,即 HQL(Hibernate查询语言)或 EJB QL(Enterprise JavaBeans查询语言)
第一个MyBatis程序(对数据库数据的增删改操作)
添加依赖
在pom.xml中添加mybatis和数据库连接的依赖
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
配置数据源
作用是将数据库和java程序连接,需要设置数据库的用户名,密码,驱动名和要操作的数据库名字
同时,配置Mapper文件路径和别名以及日志级别
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/easydata
mybatis:
mapper-locations: classpath:mapper/*.xml
logging:
level:
org.example.dao: debug
三种接收数据方式
在使用MyBatis进行数据库操作时,接收和传递数据的方法需要谨慎选择,以确保安全性和可维护性。接收数据的方式主要有三种:通过Mapper直接接收,通过简单的字符串传递,以及通过封装类传递。
-
Mapper直接接收参数(不推荐)
Mapper直接接收参数虽然简单,但是存在潜在的安全隐患,特别是当传递参数直接拼接到SQL语句中的时候,会导致SQL注入
缺点:
容易引起SQL注入。
代码维护性差,特别是当参数增多时 -
通过简单字符串传递参数(不推荐)
将参数拼接成字符串传递,虽然能够避免一些简单场景下的拼接问题,但如果参数量较多或者包含特殊字符,就不太适用了
缺点:
当参数较多时,字符串拼接会变得不堪重负。
维护和阅读性差。 -
封装类接收参数(推荐)–有效防止SQL注入
通过使用封装类(POJO,Plain Old Java Object),可以将多个参数封装到一个对象中传递。这种方法不仅能提高代码的可读性和可维护性,还能有效防止SQL注入。
所以我们编写封装类
编写封装类
salary薪资,在数据库中建议使用Decimal定义,用于精确计算金额
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;
定义mapper
${…} 和 #{…}区别
- ${…}
. . . 是字符串替换,将表达式的结果直接拼接到 S Q L 中,不进行预编译处理。作用: {...} 是字符串替换,将表达式的结果直接拼接到 SQL 中,不进行预编译处理。 作用: ...是字符串替换,将表达式的结果直接拼接到SQL中,不进行预编译处理。作用:{…} 用于替换变量,可以是字段名、表名、条件等,不进行类型转换或预处理。
示例:
<select id="getUserById" resultType="User">
SELECT * FROM users WHERE id = ${userId}
</select>
如果 userId 是 1,则实际执行的 SQL 是 SELECT * FROM users WHERE id = 1。
注意事项:
${…} 可能导致 SQL 注入攻击,因为它直接将内容替换到 SQL 中,不会对输入进行处理和验证。
- #{…}
#{…} 是参数占位符,MyBatis 会将该参数预编译成 JDBC 可以识别的格式,可以防止 SQL 注入攻击。
作用:#{…} 用于传递参数,MyBatis 会将参数转换为对应的 JDBC 类型,并进行预编译处理,以防止 SQL 注入。
示例:
<select id="getUserById" resultType="User">
SELECT * FROM users WHERE id = #{userId}
</select>
如果 userId 是 1,MyBatis 会预处理成 PreparedStatement,然后执行查询。
优势:
安全性更高:预编译参数可以防止 SQL 注入攻击,因为输入参数不会直接拼接到 SQL 语句中。
支持多种数据库的类型转换:MyBatis 会根据数据库的类型自动转换参数。
区别总结:
${…} 是简单的字符串替换,用于动态拼接 SQL 中的字段名、表名或条件等。
#{…} 是参数化的占位符,用于传递参数并且可以防止 SQL 注入,适合用于传递参数值。
在使用 MyBatis 时,推荐使用 #{…} 来传递参数,以确保安全性和数据库类型的正确转换,避免可能的 SQL 注入问题。
SQL 注入(SQL Injection)
是一种常见的安全漏洞,指的是攻击者通过向应用程序的输入字段插入恶意的 SQL 语句,从而利用应用程序对数据库的访问权限执行未经授权的操作。具体来说,SQL 注入是利用应用程序没有正确过滤或转义用户输入的情况下,将恶意的 SQL 代码插入到查询语句中的一种攻击方式。
SQL 注入通常发生在以下情况下:
未正确过滤用户输入:如果应用程序在构建 SQL 查询时,直接将用户提供的数据插入到 SQL 查询中,而没有对输入进行充分验证和过滤,攻击者可以通过输入特定的字符或结构改变原始查询的意图。
动态拼接 SQL 语句:如果应用程序使用字符串拼接的方式构建 SQL 查询,而不是使用参数化查询(Prepared Statement),攻击者可以在输入中插入 SQL 片段,从而改变查询的行为。
攻击方法:
绕过身份验证和授权:通过注入恶意的 SQL 查询,攻击者可以绕过登录认证或者获取未授权的访问权限。
窃取敏感信息:攻击者可以利用注入来获取数据库中的敏感信息,如用户凭据、个人数据等。
修改数据:攻击者可以修改数据库中的数据,包括插入新数据、更新或删除现有数据,甚至是完全删除表格。
执行管理操作:攻击者可以执行数据库管理操作,如创建、删除表格或者数据库。
定义mapper
<?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="org.example.dao.IStaffDao">
<!--SQL语句-->
<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>
定义数据访问层接口
import org.apache.ibatis.annotations.Mapper;
import org.example.bean.Staff;
@Mapper
public interface IStaffDao {
String getNow();
int addStaff(Staff staff);
int delStaff(int id);
int editStaff(Staff staff);
}
编写业务层
@RestController
public class EasyController {
@Autowired
IStaffDao dao;
@GetMapping("now")
public String now(){
return dao.getNow();
}
@PostMapping("staff")
public String addStaff(Staff staff){
dao.addStaff(staff);
return "success";
}
@DeleteMapping("staff/{id}")
public String delStaff(@PathVariable int id){
dao.delStaff(id);
return "success";
}
@PutMapping("staff")
public String editStaff(Staff staff){
dao.editStaff(staff);
return "success";
}
}
编写启动类
@SpringBootApplication
public class EasySpringMybatis {
public static void main(String[] args) {
SpringApplication.run(EasySpringMybatis.class,args);
}
}
程序运行
程序运行后,搭配使用java编程程序(idea或其他),数据库管理程序(navicat或其他)和Apipost检验程序是否运行正常
标签:第一天,数据库,笔记,参数,SQL,MyBatis,id,staff From: https://blog.csdn.net/Word_seeker/article/details/140936168