MyBatis 框架的搭建及使用

news2025/1/27 12:01:21

目录

  • 什么是 MyBatis
  • MyBatis 环境的搭建
    • 添加 MyBatis 依赖
    • 设置 MyBatis 配置
  • 根据 MyBatis 写法完成数据库操作
    • 查询操作(无参)
      • 定义接口
      • 使用 XML 实现接口
      • 类中的属性名与数据库表中字段名不一致怎么办 ?
    • 查询操作(有参)
      • ${} 和 #{} 有啥区别 ?
      • 使用 ${} 会出现的问题
      • like 查询
    • 删除操作
    • 修改操作
    • 添加操作

什么是 MyBatis

MyBatis 是⼀款优秀的持久层框架,它⽀持⾃定义 SQL、存储过程以及⾼级映射. MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作.

简单来说 MyBatis 是更简单完成程序和数据库交互的⼯具,也就是更简单的操作和读取数据库⼯具.
(它的底层是基于 JDBC 的,就像 Spring 底层是基于 Service 一样,都是为了让操作更简便)

MyBatis 环境的搭建

分两步 :

  1. 添加 MyBatis 依赖
  2. 设置 MyBatis 配置

添加 MyBatis 依赖

在这里插入图片描述
注意 : 这个时候项目是运行不起来的, 因为我们添加了 MyBatis 依赖, 服务器就需要知道它具体要连接哪台数据库, 以及账户密码等, 这就需要设置配置了.

设置 MyBatis 配置

# 数据库连接配置(mycnblog 对应你要操作的数据库名)
spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# 配置 mybatis xml 的⽂件路径
# 在 resources/mybatis 创建所有表的 xml ⽂件
mybatis.mapper-locations=classpath:mybatis/**Mapper.xml

# 配置 MyBatis 执行时打印 SQL(可选配置)
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.example.demo=debug

根据 MyBatis 写法完成数据库操作

查询操作(无参)

先来看看数据库里有啥 :
在这里插入图片描述
我们就对 userinfo 进行操作 :

定义接口

首先得定义 model 层的 Userinfo 类 :

@Data
public class Userinfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int state;
}

再在 dao 层定义接口 :

@Mapper  //数据持久层标志
public interface UserMapper {
	//查询声明
    //getAll 是操作数据库的方法名
    List<Userinfo> getAll();
}

使用 XML 实现接口

在 resources 下 创建 mybatis 目录(配置中定义的), 然后在该目录下定义一个 UserMapper.xml (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="com.example.demo.dao.UserMapper">
    <select id="getAll" resultType="com.example.demo.model.Userinfo">
        select * from userinfo
    </select>
</mapper>

select 查询操作
id=“getAll” 实现接口中的方法
resultType=“com.example.demo.model.Userinfo” 返回的数据类型
select * from userinfo 具体的 sql 语句(注意不要加分号)

在测试类中进行测试 :

@SpringBootTest  //项目运行在 spring 容器中
class UserMapperTest {

	@Autowired
	private UserMapper userMapper;

	@Test
	void getAll() {
		List<Userinfo> list = userMapper.getAll();
		System.out.println(list);
	}
}

在这里插入图片描述

类中的属性名与数据库表中字段名不一致怎么办 ?

如果类中的属性名, 与数据库表中的字段名不一致, 则查询不到结果.

@Data
public class Userinfo {
	//将 id 改为iid
    private int iid;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int state;
}

iid 为默认的初识值 :
在这里插入图片描述

解决方法 :

  1. 将类中的属性名与数据库表中字段名保持一致
  2. 使用 sql 语句的 as 进行列名 (字段名) 重命名, 让列名 (字段名) 等于属性名.
 <select id="getAll" resultType="com.example.demo.model.Userinfo">
        select id as iid,username,password from userinfo
    </select>

在这里插入图片描述

  1. 定义一个 resultMap, 将属性名和字段名进行手动映射.

type 里是要映射的类

    <resultMap id="BaseMap" type="com.example.demo.model.Userinfo">
        <id column="id" property="iid"></id>
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
        <result column="photo" property="photo"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="state" property="state"></result>
    </resultMap>
    <select id="getAll" resultMap="BaseMap">
        select * from userinfo
    </select>

在这里插入图片描述

查询操作(有参)

通过用户 id 查询用户信息 :

@Mapper 
public interface UserMapper {

    //根据 id 查找用户信息
    //不能用 int 来接收对象, 因为传递的参数可能为空, int 接收会报错
    Userinfo getUserById(@Param("id") Integer uid);
}

注意 :
上面 @Param 里的参数名与下面 ${} 里的参数名一致
一般来说上面的两个参数都会统一参数名, 这里为了便于说明区别没统一
下面 id 接收时, 也可以用 #{id}

<?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.example.demo.dao.UserMapper">

    <select id="getUserById" resultType="com.example.demo.model.Userinfo">
        select * from userinfo where id=${id}
    </select>
</mapper>
@SpringBootTest  
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void getUserById() {
        Userinfo userinfo = userMapper.getUserById(1);
        System.out.println(userinfo.toString());
    }
}

在这里插入图片描述

${} 和 #{} 有啥区别 ?

通过上面结果可以看到使用 ${} 时, MySQL 执行如下 :
在这里插入图片描述
而使用 #{} 替代, 则是这样 :
在这里插入图片描述

${} 和 #{} 都是 MyBatis 中用来替换参数的.
${} 是直接替换, 而 #{} 是预执行.
#{} 规定了在 ? 里必须是一个参数, 不能是 SQL 命令或 SQL关键字, 而 ${} 里则可以是 SQL 命令或 SQL 语句.
这也就体现了 #{} 是安全的, ${} 是不安全的, 会有 SQL 注入问题.
使用 ${} 返回的参数, 一定得要能被穷举.

使用 ${} 会出现的问题

就拿用户登录来举例, 一般来说登录都是要通过用户名和密码的 :

@Mapper  
public interface UserMapper {
    //用户登录
    Userinfo login(@Param("username")String username, 
    			   @Param("password")String password);
}
<?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.example.demo.dao.UserMapper">

    <select id="login" resultType="com.example.demo.model.Userinfo">
        select * from userinfo where username=${username} and password=${password}
    </select>
</mapper>
@SpringBootTest  
class UserMapperTest {

    @Test
    void login() {
        Userinfo userinfo = userMapper.login("admin","admin");
        System.out.println(userinfo.toString());
    }
}

在这里插入图片描述
可以看到这个 SQL 语句明显有问题, 正常写法得加上单引号 ‘admin’, 使用 #{} 则没有这个问题.
这个问题也可以解决, 通过手动加单引号就行 :

    <select id="login" resultType="com.example.demo.model.Userinfo">
        select * from userinfo where username='${username}' and password='${password}'
    </select>

这样明显更繁琐了, 而且不安全, 会有 SQL 注入风险 :

    @Test
    void login() {
        Userinfo userinfo = userMapper.login("admin","' or 1='1");
        System.out.println(userinfo.toString());
    }

这里通过特殊语句, 来达到非法登录的目的 :
在这里插入图片描述

可以看到, 我明明没有输入正确密码, 却可以获取到用户信息, 这就是 SQL注入.

like 查询

    List<Userinfo> getLikeList(@Param("username") String username);

用 数据库函数 concat 进行拼接 :

    <select id="getLikeList" resultType="com.example.demo.model.Userinfo">
        select * from userinfo where
        username like concat('%',#{username},'%')
    </select>
    @Test
    void getLikeList() {
        System.out.println(userMapper.getLikeList("管"));
    }

在这里插入图片描述

删除操作

删除、修改、添加操作默认返回的是受影响的行数

@Mapper  
public interface UserMapper {

    //删除操作
    int delById(@Param("id") Integer id);
}
	<!--这里返回类型可以省略-->
    <delete id="delById">
        delete from userinfo where id=#{id}
    </delete>

修改操作

@Mapper  
public interface UserMapper {

    //修改操作
    int update(Userinfo userinfo);
}
    <update id="update">
        update userinfo set username=#{username} where id=#{id}
    </update>
    @Test
    void update() {
        Userinfo userinfo = new Userinfo();
        userinfo.setId(1);
        userinfo.setUsername("管理员");
        int result = userMapper.update(userinfo);
        System.out.println("受影响的行数 : " + result);
    }

在这里插入图片描述
在这里插入图片描述

添加操作

  1. 拿到受影响的行数
    //添加操作
    int add(Userinfo userinfo);
    <insert id="add">
        insert into userinfo(username,password,photo)
        value(#{username},#{password},#{photo})
    </insert>
    @Test
    void add() {
        Userinfo userinfo = new Userinfo();
        userinfo.setUsername("王三");
        userinfo.setPassword("123456");
        userinfo.setPhoto("/image/ddd.png");
        int result = userMapper.add(userinfo);
        System.out.println("受影响的行数 : " + result);
    }

在这里插入图片描述
在这里插入图片描述

  1. 拿到自增 id :
    int insert(Userinfo userinfo);
    <insert id="insert" useGeneratedKeys="true"
            keyColumn="id" keyProperty="id">
        insert into userinfo(username,password,photo)
        value(#{username},#{password},#{photo})
    </insert>

keyColum : 设置数据库自增主键字段名
keyProperty : 设置数据库自增 id 赋值的属性

    @Test
    void insert() {
        Userinfo userinfo = new Userinfo();
        userinfo.setUsername("二哈");
        userinfo.setPassword("123456456");
        int result = userMapper.insert(userinfo);
        System.out.println("受影响的行数 : " + result + ", ID : " + userinfo.getId());
    }

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/924261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CypherRAT、CraxsRATAndroid系列恶意软件“始作俑者”曝光!

近日&#xff0c;恶意软件系列 CypherRAT 和 CraxsRAT 的创建者曝光&#xff0c;是一位名为 EVLF 的叙利亚威胁行为者。 网络安全公司Cyfirma在上周发布的一份报告中提到&#xff1a;这些RAT旨在允许攻击者远程执行实时操作&#xff0c;并控制受害者设备的摄像头、位置和麦克风…

职场的心灵疗愈:如何战胜压力与燃尽?

职场压力的根源 当代职场的变革与挑战 在数字化时代,职场的变革速度前所未有。新的技术和工具不断涌现,要求员工持续学习和适应。例如,云计算、大数据和人工智能等技术正在改变许多行业的工作方式。这些技术为我们带来了便利,但同时也带来了学习和适应的压力。 此外,全球…

keepalived+lvs(DR)(四十六)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、作用 二、调度器配置 三、web节点配置 一、作用 使用keepalived解决lvs的单点故障 高可用集群 二、调度器配置 安装keepalived yum install -y k…

leetcode:电话号码的字母组合(详解)

题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 示例 1&#xff1a; 输入&#xff1a;digits "23" 输出…

基于javaweb的新生报到系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

用Idea把SpringBoot项目打包镜像上传至docker

1、设置docker把2375端口开起来 命令查看docker装在哪里 vim docker.service 新增 -H tcp://0.0.0.0:2375 -H unix://var/run/docker.sock 2、配置Dockerfile 我在跟pom同一层 3、配置docker-maven-plugin <plugin><groupId>com.spotify</groupId><arti…

LAMP架构介绍配置命令讲解

LAMP架构介绍配置命令讲解 一、LAMP架构介绍1.1概述1.2LAMP各组件的主要作用1.3各组件的安装顺序 二、编译安装Apache httpd服务---命令讲解1、关闭防火墙&#xff0c;将安装Apache所需的软件包传到/opt/目录下2、安装环境依赖包3、配置软件模块4、编译安装5、优化配置文件路径…

API接口管理平台:提高开发效率和节省时间的解决方案

随着互联网的迅速发展&#xff0c;很多业务已经可以通过API接口实现&#xff0c;使得开发者可以更快速地开发出高质量的软件。然而&#xff0c;随着API数量的增加&#xff0c;管理这些API也变得尤为困难。因此&#xff0c;API接口管理平台应运而生。本文将探讨如何使用API接口管…

中国人民大学与加拿大女王大学合办金融硕士毕业证书是双证么?

中国人民大学与加拿大女王大学合办金融硕士毕业证书是双证么&#xff1f; 无需参加全国联考获国家承认双证中国教育部留学服务中心可认证 是的 双证的 学位授予 1、完成本项目十门课程&#xff0c;通过考核符合毕业要求的学生将获得由女王大学颁发的金融硕士学位证书&#x…

论文笔记: MOGRIFIER LSTM

2020 ICLR 修改传统LSTM 当前输入和隐藏状态充分交互&#xff0c;从而获得更佳的上下文相关表达 1 Mogrifier LSTM LSTM的输入X和隐藏状态H是完全独立的 机器学习笔记&#xff1a;GRU_gruc_UQI-LIUWJ的博客-CSDN博客这篇论文想探索&#xff0c;如果在输入LSTM之前&#xf…

亿级月活的社交 APP,陌陌如何做到 3 分钟定位故障?

一分钟精华速览 本文概述了挚文集团&#xff08;陌陌和探探母公司&#xff09;在微服务架构下解决故障定位问题中遇到的痛点、解决方案以及取得的效果。通过构建统一可观测平台&#xff0c;实现了故障快速定位&#xff0c;大幅提升了问题定位的效率。文中还讨论了存储优化、数…

SpringBoot案例-配置文件-@ConfigurationProperties

问题分析 在往期的配置参数的文章中&#xff0c;对于阿里云OSS的参数时设置在yml配置文件中&#xff0c;然后使用Value&#xff08;”${}“&#xff09;对参数进行赋值&#xff0c;具体如下&#xff1a; 此种方法比较繁琐 问题解决 使用注解 Data 为变量自动生成get/set方…

CrystalNet .Net VCL for Delphi Crack

CrystalNet .Net VCL for Delphi Crack VCL或更为人所知的可视化组件库是基于一个面向对象的框架&#xff0c;什么是用户对开发人员和事件的Microsoft Windows应用程序的接口。可视化组件库是用对象Pascal编写的。它主要是为使用Borland而开发的&#xff0c;它具有与Delphi以及…

vue关闭弹窗刷新父页面 this.$refs

代码截图 主页面 弹出框页面 接这一篇文章后续 参考链接

专题-【B树的构建与删除】

构建&#xff1a; 删除&#xff1a; 叶子结点直接删&#xff1b; 非叶结点 找前驱&#xff08;左子树最右边&#xff09;/后继&#xff08;右子树最左边&#xff09;元素覆盖即可&#xff08;满足关键字个数取值范围&#xff09;&#xff1b; 这个更详细 『数据结构与算法』…

JAVA-编程基础-09-常用工具类

Lison <dreamlison163.com>, v1.0.0, 2023.04.16 JAVA-编程基础-09-常用工具类 文章目录 JAVA-编程基础-09-常用工具类Arrays工具类创建数组copyOfcopyOfRangefill 数组比较数组排序数组检索数组转流打印数组数组转 ListsetAllparallelPrefix StringUtils工具类字符串判…

PHP 安装Composer,vue前端依赖包

电脑安装Composer 官网下载&#xff1a;https://getcomposer.org/Composer-Setup.exe 后端安装&#xff1a; 检查是否安装依赖&#xff1a; 安装Composer install 或 Composer i 前端安装&#xff1a; yarn install 安装依赖

数组和指针练习(3)

题目&#xff1a; int main() { int a[5][5]; int(*p)[4]; p a; printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]); return 0; } 思路分析&#xff1a; int(*p)[4]; 定义了指针变量p是一个数组指针&#xff0c;且该数组指…

Spring MVC详解

文章目录 一、SpringMVC1.1 引言1.2 MVC架构1.2.1 概念1.2.2 好处 二、开发流程2.1 导入依赖2.2 配置核心(前端)控制器2.3 后端控制器2.4 配置文件2.5 访问 三、接收请求参数3.1 基本类型参数3.2 实体收参【重点】3.3 数组收参3.4 集合收参 【了解】3.5 路径参数3.6 中文乱码 四…

Web 开发 Django 模板

上次为大家介绍了 Django 的模型和自带的管理工具&#xff0c;有了这个工具就可以全自动地根据模型创建后台管理界面&#xff0c;以供网站管理者更方便的管理网站数据。有了网站数据&#xff0c;那怎么样更方便又好看的展示给用户看呢&#xff1f;目前流行的 Web 框架基本都采用…