【大家好,我是爱干饭的猿,本文重点介绍ORM 框架和Mybatis的关系、如何通过注解 或者 通过XML配置文件的使用Mybatis,以及参数占位符 #{} 和 ${} 的区别, 什么是sql 注入。
后续会继续分享其他重要知识点总结,如果喜欢这篇文章,点个赞👍,关注一下吧】
上一篇文章:《【SSM】Spring AOP 统一问题处理(重点:Spring AOP 实现原理)》
🤞目录🤞
🎁1.MyBatis 是什么?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 去除了几乎所有的 JDBC 代码以及设置参数和获 取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
简单来说 MyBatis 是更简单完成程序和数据库交互的工具,也就是更简单的操作和读取数据库工具。
🎁2. 什么是ORM框架?
ORM 把数据库映射为对象:
- 数据库表(table)--> 类(class)
- 记录(record,行数据)--> 对象(object)
- 字段(field) --> 对象的属性(attribute)
一般的 ORM 框架,会将数据库模型的每张表都映射为一个 Java 类。 也就是说使用 MyBatis 可以像操作对象一样来操作数据库中的表,可以实现对象和数据库表之间的转换。
MyBatis 也是一个 ORM 框架,ORM(Object Relational Mapping),即对象关系映射。在面向对象编程语言中,将关系型数据库中的数据 与对象建立起映射关系,进而自动的完成数据与对象的互相转换:
1. 将输入数据(即传入对象)+SQL 映射成原生 SQL
2. 将结果集映射为返回对象,即输出对象
一些其他框架:
- Hibernate框架:偏向简化SQL的模式
- MyBatis框架:偏向ORM的模式
- Spring 内部提供的JdbcTemplate:偏向简化SQL的模式
- JPA :完全倒向了ORM的形式,建表的过程都被抽象,我们看到的只有类(我写了类,框架根据类建表)
🎁3. MyBatis 的使用
3.1 添加MyBatis框架支持
1. 新项目添加MyBatis框架
2. 旧项目添加MyBatis框架
a. 使用 EditStarters插件
b. 手动添加
-
<!-- 把 DataSource对象注册到Spring 中-->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-data-jdbc
</artifactId>
-
</dependency>
-
<!-- 添加 mybatis 框架 -->
-
<dependency>
-
<groupId>org.mybatis.spring.boot
</groupId>
-
<artifactId>mybatis-spring-boot-starter
</artifactId>
-
<version>2.2.2
</version>
-
</dependency>
-
<!-- 添加 MySQL 驱动 -->
-
<dependency>
-
<groupId>mysql
</groupId>
-
<artifactId>mysql-connector-java
</artifactId>
-
<scope>runtime
</scope>
-
</dependency>
3.2 配置连接字符串和MyBatis
此步骤需要进行两项设置,数据库连接字符串设置和 MyBatis 的 XML 文件配置。
1. 配置连接字符串
如果是 application.yml 添加如下内容:
-
spring:
-
datasource:
-
url: jdbc:mysql://127.0.0.1:3306/***?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
-
username: root
-
password: 123456
2. 配置 MyBatis 中的 XML 路径
通过XML配置文件的形式使用Mybatis 时需要配置,通过注解使用Mybatis时,不需要配置
-
mybatis:
-
mapper-locations: classpath:mapper/**.xml
3.3 通过注解使用Mybatis
定义Mapper 接口
-
@Repository
// 消除报错
-
@Mapper
// Mapper 注解
-
public
interface
UserMapper {
-
-
}
1. 查询
-
// 1. 查询
-
// 1.1 通过uid 查询得到Map对象
-
@Select("select uid, username, password from users where uid = #{uid}")
-
Map<String, Object>
select1
(@Param("uid") int uid);
-
-
// 1.2 通过uid 查询得到User类对象
-
@Select("select uid, username, password from users where uid = #{uid}")
-
UserDO
select2
(@Param("uid") int uid);
2. 插入
-
// 2. 插入
-
// 2.1 插入,返回插入成功的条数
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
int
insert1
(UserDO userDO);
-
-
// 2.2 由于用不到这个返回值,所以写成 void 更常见
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
void
insert2
(UserDO userDO);
-
-
// 2.3 插入后拿到自增id
-
// 通过 @Options 注解,添加一些配置,得到自增主键,设置成 uid
-
// keyProperty : 对象的属性名是 uid
-
// keyColumn : 表的字段名的 uid
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
@Options(useGeneratedKeys = true, keyProperty = "uid", keyColumn = "uid")
-
void
insert3
(UserDO userDO);
3. 修改
-
// 3. 修改
-
@Update("update users set username = #{username}, password = #{password} where uid = #{uid}")
-
int
update
(UserDO userDO);
4. 删除
-
// 4. 删除
-
@Delete("delete from users where uid = #{uid}")
-
int
delete
(@Param("uid") int uid);
5. 总览(增删查改)
-
import org.apache.ibatis.annotations.*;
-
import org.springframework.stereotype.Repository;
-
import java.util.Map;
-
-
@Repository
// 消除报错
-
@Mapper
// Mapper 注解
-
public
interface
UserMapper {
-
-
// 1. 查询
-
// 1.1 通过uid 查询得到Map对象
-
@Select("select uid, username, password from users where uid = #{uid}")
-
Map<String, Object>
select1
(@Param("uid") int uid);
-
-
// 1.2 通过uid 查询得到User类对象
-
@Select("select uid, username, password from users where uid = #{uid}")
-
UserDO
select2
(@Param("uid") int uid);
-
-
// 2. 插入
-
// 2.1 插入,返回插入成功的条数
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
int
insert1
(UserDO userDO);
-
-
// 2.2 由于用不到这个返回值,所以写成 void 更常见
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
void
insert2
(UserDO userDO);
-
-
// 2.3 插入后拿到自增id
-
// 通过 @Options 注解,添加一些配置,得到自增主键,设置成 uid
-
// keyProperty : 对象的属性名是 uid
-
// keyColumn : 表的字段名的 uid
-
@Insert("insert into users (username, password) values (#{username}, #{password})")
-
@Options(useGeneratedKeys = true, keyProperty = "uid", keyColumn = "uid")
-
void
insert3
(UserDO userDO);
-
-
// 3. 修改
-
@Update("update users set username = #{username}, password = #{password} where uid = #{uid}")
-
int
update
(UserDO userDO);
-
-
// 4. 删除
-
@Delete("delete from users where uid = #{uid}")
-
int
delete
(@Param("uid") int uid);
-
}
3.4 通过XML配置文件的形式使用Mybatis
先配置 MyBatis 中的 XML 路径,然后在mapper下 .xml 文件中写
定义Mapper 接口:
-
import org.apache.ibatis.annotations.Mapper;
-
import org.apache.ibatis.annotations.Param;
-
import org.springframework.stereotype.Repository;
-
import java.util.List;
-
-
@Repository
-
@Mapper
-
public
interface
UserMapper {
-
// 1. 查询
-
// 1.1 单个查询
-
User
selectOneByUid
(@Param("uid") int uid);
-
// 1.2 多个查询
-
List<User>
selectListByUidList
(@Param("uidList") List<Integer> uidList);
-
// 1.3 动态查询
-
User
selectByUser
(@Param("user") User user);
-
-
// 2. 插入
-
// 2.1 单个插入
-
int
insertOneUser
(@Param("user") User user);
-
// 2.1 批量插入
-
int
insertBatch
(@Param("userList") List<User> userList);
-
-
// 3. 修改
-
void
update
(int uid , String username);
-
-
// 4. 删除
-
void
delete
(int uid);
-
}
0. 关于resultMap
使用场景:
- 字段名称和程序中的属性名不同的情况,可使用 resultMap 配置映射;
- 一对一和一对多关系可以使用 resultMap 映射并查询数据。
-
<!-- 返回字典映射-->
-
<resultMap id="xxx" type="com.haomin.mybatis_xml.User">
-
<id property="uid" javaType="Integer" column="uid" jdbcType="INTEGER" />
-
<result property="username" javaType="String" column="username" jdbcType="VARCHAR" />
-
<result property="password" column="password" />
-
</resultMap>
1. 查询
-
<!-- 1.1 单个查询 -->
-
<select id="selectOneByUid" resultType="com.haomin.mybatis_xml.User" parameterType="int">
-
select uid, username, password from users where uid = #{uid}
-
</select>
-
-
<!-- 1.2 多个查询 -->
-
<select id="selectListByUidList" resultMap="xxx" parameterType="List">
-
select uid, username, password from users where uid in (
-
<foreach collection="uidList" item="id" separator=", ">
-
#{id}
-
</foreach>
-
) order by uid
-
</select>
-
-
<!-- 1.3 动态查询-->
-
<select id="selectByUser" resultMap="xxx" parameterType="com.haomin.mybatis_xml.User">
-
select uid, username, password from users where
-
<if test="user.uid != null">
-
uid = #{user.uid}
-
</if>
-
<if test="user.username != null">
-
and username = #{user.username}
-
</if>
-
<if test="user.password != null">
-
and password = #{user.password}
-
</if>
-
</select>
2. 插入
-
<!-- 2.1 单个插入-->
-
<insert id="insertOneUser" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
-
insert into users (username, password) values
-
(#{user.username}, #{user.password})
-
</insert>
-
-
<!-- 2.2 批量插入-->
-
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
-
insert into users (username, password) values
-
<foreach collection="userList" item="user" separator=", ">
-
(#{user.username}, #{user.password})
-
</foreach>
-
</insert>
3. 修改
-
<!-- 3. 修改-->
-
<update id="update">
-
update users set username = #{username} where uid = #{uid}
-
</update>
4. 删除
-
<!-- 4. 删除-->
-
<delete id="delete">
-
delete from users where uid = #{uid}
-
</delete>
5. 总览(增删查改)
-
<?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.haomin.mybatis_xml.UserMapper">
-
<!-- 返回字典映射-->
-
<resultMap id="xxx" type="com.haomin.mybatis_xml.User">
-
<id property="uid" javaType="Integer" column="uid" jdbcType="INTEGER" />
-
<result property="username" javaType="String" column="username" jdbcType="VARCHAR" />
-
<result property="password" column="password" />
-
</resultMap>
-
-
<!-- 1.1 单个查询 -->
-
<select id="selectOneByUid" resultType="com.haomin.mybatis_xml.User" parameterType="int">
-
select uid, username, password from users where uid = #{uid}
-
</select>
-
-
<!-- 1.2 多个查询 -->
-
<select id="selectListByUidList" resultMap="xxx" parameterType="List">
-
select uid, username, password from users where uid in (
-
<foreach collection="uidList" item="id" separator=", ">
-
#{id}
-
</foreach>
-
) order by uid
-
</select>
-
-
<!-- 1.3 动态查询-->
-
<select id="selectByUser" resultMap="xxx" parameterType="com.haomin.mybatis_xml.User">
-
select uid, username, password from users where
-
<if test="user.uid != null">
-
uid = #{user.uid}
-
</if>
-
<if test="user.username != null">
-
and username = #{user.username}
-
</if>
-
<if test="user.password != null">
-
and password = #{user.password}
-
</if>
-
</select>
-
-
<!-- 2.1 单个插入-->
-
<insert id="insertOneUser" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
-
insert into users (username, password) values
-
(#{user.username}, #{user.password})
-
</insert>
-
-
<!-- 2.2 批量插入-->
-
<insert id="insertBatch" useGeneratedKeys="true" keyProperty="uid" keyColumn="uid">
-
insert into users (username, password) values
-
<foreach collection="userList" item="user" separator=", ">
-
(#{user.username}, #{user.password})
-
</foreach>
-
</insert>
-
-
<!-- 3. 修改-->
-
<update id="update">
-
update users set username = #{username} where uid = #{uid}
-
</update>
-
-
<!-- 4. 删除-->
-
<delete id="delete">
-
delete from users where uid = #{uid}
-
</delete>
-
</mapper>
当然还有更多用法:可以参考 Mybatis 官方文档
3.5 参数占位符 #{} 和 ${} 和 sql 注入
#{}:预编译处理。
${}:字符直接替换。
#{}预编译处理是指:MyBatis 在处理#{}时,会将 SQL 中的 #{} 替换为?号,使用 PreparedStatement 的 set 方法来赋值,编译后会带上 ‘ ’。
${}直接替换:是 MyBatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
结论:
- 用于查询的字段,尽量使用 #{} 预查询的方式,如果用${} 可能会出现sql注入问题。
- 使用 ${sort} 可以实现排序查询或者分页,而使用 #{sort} 就不能实现排序查询了,因为当使用 #{sort} 查询时,如果传递的值为 String 则会加单引号,就会导致 sql 错误。
sql 注入代码例子:
执行:
select * from userinfo where username = '${name}' and password = '${pwd}'
当sql 为 : ' or 1=1 时
执行语句:
select * from users where username = ' or 1=1 and password = ' or 1=1;
当然,Mybatis 还有更多用法:可以参考 Mybatis 官方文档
分享到此,感谢大家观看!!!
如果你喜欢这篇文章,请点赞加关注吧,或者如果你对文章有什么困惑,可以私信我。
🏓🏓🏓
转载:https://blog.csdn.net/m0_62218217/article/details/127392647