MyBatis操作数据库常用用法总结1

文章目录

      • 1.单表查询
        • 1.1返回所有的表记录
        • 1.2根据id查找结果
        • 1.3根据名字查找结果
      • 2.单表修改
        • 2.1修改密码
      • 3.单表删除
        • 3.1根据id删除信息
      • 4.单表增加(根据业务情况返回)
        • 4.1添加返回影响的行数
        • 4.2添加返回影响行数和id
      • 5.多表查询(多)
        • 一对一
        • 多对多
      • 参数占位符#{}和${}区别:
        • like查询
      • sql注入

说明:
1.这里写完interface和xml中的内容,使用数据库和单元测试进行了检验
2. Mybatis拿参数的方式和SpringBoot一样,最通用的就是在加个@Param注解在这里插入图片描述
对应的sql中的xml就需要用${ord}或者#{ord}的方式获取
3.如果传对象,一般不用再要@Param注解,如UserEntity user,这个时候xml写法:
直接写对象的名字,直接写属性名(框架帮助我们自动完成了映射)

4.多表删除和多表增加都可以在Serive层进行任务编排,一个一个属性的注入,对应的完成任务,所以mapper这一层只需要考虑单表的增删改查和多表的联合查询问题
5.数据库如果使用拼接,java这边使用大小驼峰的话,spring框架可以自动映射

1.单表查询

1.1返回所有的表记录

1)在UserMapper中建立对应的接口

package com.example.demo.mapper;
import com.example.demo.entity.UserEntity;
//名字是历史原因(以前的类可能还是ibatis这个名)
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;import java.util.List;
//mapper层就是数据持久层,叫做repostories也行
@Mapper//表明是组件之一
public interface UserMapper {//单表查询List<UserEntity> getAll();
}

2)在UserMapper.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.example.demo.mapper.UserMapper"><!--    1.namespace:要实现的类包名+接口名--><!--    2.id:实现的对应接口里的方法名--><!--实现什么方法,返回值--><select id="getAll" resultType="com.example.demo.entity.UserEntity">select * from userinfo
<!--        不用写分号--></select>
</mapper>

3)返回UserMapper中,点中方法,右键生成测试方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IVMI4zqU-1691473708859)(F:\typora插图\image-20230515171810665.png)]

4)补充测试方法

  • 为类加上@SpringBootTest注解
  • 采用DI的方式注入UserMapper对象
package com.example.demo.mapper;import com.example.demo.entity.UserEntity;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;import java.util.List;import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest//表示当前单元测试是运行在Spring Boot环境下的
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid getAll() {List<UserEntity> list=userMapper.getAll();System.out.println(list);}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mRPXJbyq-1691473708860)(F:\typora插图\image-20230515173216919.png)]

在配置完对应的配置项,我们可以看到下边的测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wlAzd0Uz-1691473708860)(F:\typora插图\image-20230515173432418.png)]

下边是数据库中的验证结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LhFGdpac-1691473708861)(F:\typora插图\image-20230515173727230.png)]

1.2根据id查找结果

1)mapper中添加方法声明

UserEntity getUserById(@Param("id") Integer id);

2)xml文件中添加方法实现:

<select id="getUserById" resultType="com.example.demo.entity.UserEntity">select * from userinfo where id=#{id}
</select>

3)生成、补充、运行测试代码,去数据库进行验证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mzvLJ6U3-1691473708861)(F:\typora插图\image-20230515172100379.png)]

在配置完对应的配置项,我们可以看到下边的测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MjodaacV-1691473708861)(F:\typora插图\image-20230515172909652.png)]

下边是数据库中对应的验证结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uip5Vf0f-1691473708862)(F:\typora插图\image-20230515173001207.png)]

1.3根据名字查找结果

1)mapper中添加方法声明

UserEntity getUserByUsername(@Param("username") String username);

2)xml文件中添加方法实现:

    <select id="getUserByUsername" resultType="com.example.demo.entity.UserEntity">select * from userinfo where username=#{username}</select>

3)生成、补充、运行测试代码,去数据库进行验证

    @Testvoid getUserByUsername() {
//        直接替换没有单引号UserEntity user=userMapper.getUserByUsername("zhangsan");System.out.println(user);}

在配置完对应的配置项,我们可以看到下边的测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KVgmX8q4-1691473708862)(F:\typora插图\image-20230515175628146.png)]

下边是数据库中对应的验证结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EVK6Y5o0-1691473708863)(F:\typora插图\image-20230515175709082.png)]

2.单表修改

这里使用的标签是update,这里只有一个id属性名,没有namespace其他的,至于resultType,因为方法那里默认就是返回int类型,所以可以省略不写。

一般来说修改用户名和密码是比较高频的操作,所以我们这里以修改密码为例。

2.1修改密码

代码实现步骤:
mapper中写接口方法–》xml中写对应sq语句—>添加对应的测试方法,进行校验–》数据库校验(略)

//修改密码
int updatePassword(@Param("id")Integer id,@Param("password")String password,@Param("newPassword")String newPassword);
    <update id="updatePassword">
<!--        默认返回值就是int-->
<!--        select和update标签的区别-->update userinfo set password=#{newPassword}where id=#{id} and password=#{password}</update>
//默认污染,但是可以设置成不污染的
@Transactional//不会污染了==》会进行事务回滚
@Test
void updatePassword() {int result=userMapper.updatePassword(1,"admin","abcdef");System.out.println("修改"+result);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ttkM2UWH-1691473708863)(F:\typora插图\image-20230515180219234.png)]

记得加@Transactional注解,不污染数据库,他可以加载方法上,也可以加载类上。

3.单表删除

这里使用的delete标签,只需要设置一个参数id,和update一样,默认返回受影响的行数。

3.1根据id删除信息

//删除用户
int delById(@Param("id")Integer id);
<delete id="delById">delete from userinfo where id=#{id}
</delete>
@Transactional
@Test
void delById() {int result=userMapper.delById(1);System.out.println("删除"+result);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JKzpkfKD-1691473708864)(F:\typora插图\image-20230515180440846.png)]

4.单表增加(根据业务情况返回)

这里使用的是insert标签,和前边两个标签一样,默认返回受影响的行数。

4.1添加返回影响的行数

以登录场景为例,推荐传递对象而不是传递两个参数,方便后续维护,否则会影响整个调用链。

//添加用户
int addUser(UserEntity user);
<insert id="addUser">insert into userinfo(username,password) values(#{username0},#{password})
<insert>
@Transactional
@Test
void addUser() {UserEntity user = new UserEntity();user.setUsername("zhangsan");
//        user.setPassword("123456");int result = userMapper.addUser(user);System.out.println("添加:" + result);}

如果一批用户需要插入,看后边的动态sql,使用list

4.2添加返回影响行数和id

需要使用insert标签中userGeneratedKeys和keyProperty属性,第一个是是否生成自增主键,设置成true,第二个是将返回的主键id放到我们想要的变量中。

//添加用户,并返回id
int addUserGetId(UserEntity user);
<insert id="addUserGetId" useGeneratedKeys="true" keyProperty="id">insert into userinfo(username,password) values(#{username},#{password})
</insert>
@Test
void addUserGetId() {UserEntity user = new UserEntity();user.setUsername("lisi");
//        user.set("123456");int result = userMapper.addUserGetId(user);System.out.println("添加结果:" + result);System.out.println("ID:" + user.getId());}

5.多表查询(多)

一对一

使用最多的就是left join或者right join,将查询后的结果重命名
一般实体类和数据库表是一致的,如果还要其他的,需要创建扩展类,然后继承上一层类。

@Data
public class ArticleInfoVO extends ArticleInfo {private String username;@Overridepublic String toString() {return "ArticleInfoVO{" +"username='" + username + '\'' +"} " + super.toString();}//通过看字节码知道
}

以查询用户指定文章详情为例

// 查询文章详情ArticleInfoVO getDetail(@Param("id") Integer id);
<select id="getDetail" resultType="com.example.demo.entity.vo.ArticleInfoVO">select a.*,u.username from articleinfo aleft join userinfo u on u.id=a.uidwhere a.id=#{id}</select>
 @Testvoid getDetail() {ArticleInfoVO articleInfoVO = articleMapper.getDetail(1);System.out.println(articleInfoVO);System.out.println("title:" + articleInfoVO.getTitle());}

多对多

上边一个文章 我们规定只能一个作者,但是一个作者可以有多个文章,需要进行多对多的表查询
主表应该是文章,返回的结果应该是一个文章的列表。

 List<ArticleInfoVO> getListByUid(@Param("uid") Integer uid);
<select id="getListByUid" resultType="com.example.demo.entity.vo.ArticleInfoVO">select a.*,u.username from articleinfo aleft join userinfo u on u.id=a.uidwhere a.uid=#{uid}</select>
 @Testvoid getListByUid() {Integer uid = 1;List<ArticleInfoVO> list = articleMapper.getListByUid(uid);
//stream(语法糖)使用并行方式打印,顺序不确定(不需要自己开线程池),可以通过字节码看list.stream().parallel().forEach(System.out::println);
//      使用串行方式  list.stream().forEach(System.out::println);}

参数占位符#{}和${}区别:

#{}:原理是预编译处理。MyBatis处理#{}会将sql中的#{}替换成?号,使用Preparement的set方法赋值。
: 原 理 是 字 符 串 直 接 替 换 。 M y B a t i s 处 理 {}:原理是字符串直接替换。MyBatis处理 MyBatis{}会将它替换成变量的值。
在这里插入图片描述

共同点:都可以正确处理数值型参数。

#{}优缺点:优点可以有效防止SQL注入,提高系统安全性;缺点就是当java代码中参数名和数据库关键字相同时,会报错,那个时候考虑sql内置的concat方法。

例如:select * from userinfo order by id desc(比如tb或者pdd需要按照什么样的规则进行有限展示商品asc还是desc),此时就需要使用$

${}:优点可以解决关键字与sql语句关键字相同的问题,缺点解决非数据类型数据比较麻烦,有安全问题,通常是登录场景,有sql注入问题。

但是即使是上边的场景也是需要参数可以被枚举的,是可控的,不过不建议用这种方法,最好在Controller层Service层就能进行确定,做好了服务编排,提高安全性

结论:用于查询的字段,尽量使用#{}预编译处理的方式,尤其是的时候非数据类型的,否则不仅可能会有sql注入的问题,还有sql语句中缺少对应的引号。

like查询

当参数为非数据类型时,like使用#{}会报错,因为#{}实现原理是预编译,
最终这部分就是’%‘username’’%’
而我们又不想要sql注入,这里的解决方案就是使用concat方法:

<select id="getListByName" resultType="com.example.demo.entity.UserEntity">select * from userinfo where username like concat('%',#{username},'%')</select>
    @Testvoid getListByName() {String username = "zhang";List<UserEntity> list = userMapper.getListByName(username);list.stream().forEach(System.out::println);}

sql注入

使用了不符合要求的代码查到了本不该查到的代码。最典型的便是’or 1= 1’

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[考研机试] KY20 完数VS盈数 清华大学复试上机题 C++实现

描述 一个数如果恰好等于它的各因子(该数本身除外)子和&#xff0c;如&#xff1a;6321。则称其为“完数”&#xff1b;若因子之和大于该数&#xff0c;则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。 输入描述&#xff1a; 题目没有任何输入。 输出描述&#…

CAS服务端入门使用实践

CAS服务端入门使用实践 一、前言 1.简介 CAS 是一个企业多语言单点登录解决方案&#xff0c;支持大量附加身份验证协议和功能&#xff0c;满足身份验证和授权需求的综合平台。 2.环境 Windows 10JDK 1.8git version 2.41.0.windows.3Tomcat 9.0.78Maven 3.5.3cas-overlay-…

ArcGIS在洪水灾害普查、风险评估及淹没制图中应用教程

详情点击链接&#xff1a;ArcGIS在洪水灾害普查、风险评估及淹没制图中应用教程 一&#xff1a;洪水普查技术规范 1.1 全国水旱灾害风险普查实施方案 1.2 洪水风险区划及防治区划编制技术要求 1.3 山丘区中小河流洪水淹没图编制技术要求 二&#xff1a;ArcGIS及数据管理 …

Java集合知识回顾:从分类到工具类,掌握精髓

文章目录 1. 集合的分类2. Collection 接口3. Map 接口4. 泛型5. Collections 工具类总结 在Java编程世界中&#xff0c;集合是一项极为重要的知识&#xff0c;为我们的程序设计提供了强大的数据结构和处理手段。在本篇文章中&#xff0c;我们将回顾集合的分类以及相关的重要概…

74HC595驱动7x11点阵屏(LED-7X11-JHM)DEMO

起因 由于我之前做了一个点阵时钟 &#xff0c;但是无奈LED点阵屏价格比较贵&#xff0c;所以想找一个价格较为便宜的点阵来做便宜一点的点阵方案&#xff0c;再淘宝上看到有那种五毛钱一个的7x11的LED点阵&#xff0c;所以就想着试试搞一下这种点阵屏&#xff0c;这个由于是7…

阻塞队列的安全实现,定时器的安全实现(面试易考),超详细

一、&#x1f49b; 如何实现一个线程安全的阻塞队列 目前&#xff0c;当前代码是循环队列&#xff08;还没有进行改动&#xff09; head和tail的判空判断满两种方法: 1.浪费一个格子&#xff0c;当前走到head的前一个位置&#xff0c;就认为队列满的 2.单独搞一个变量&#xff…

机器学习基础之《特征工程(4)—特征降维》

一、什么是特征降维 降维是指在某些限定条件下&#xff0c;降低随机变量&#xff08;特征&#xff09;个数&#xff0c;得到一组“不相关”主变量的过程 1、降维 降低维度 ndarry 维数&#xff1a;嵌套的层数 0维&#xff1a;标量&#xff0c;具体的数0 1 2 3... …

AAAI论文阅读

文章目录 Open-Vocabulary Multi-Label Classifcation via Multi-Modal Knowledge Transfer——知识蒸馏的范畴Med-EASi: Finely Annotated Dataset and Models for Controllable Simplifcation of Medical Texts——医学领域数据集构建“Nothing Abnormal”: Disambiguating M…

Unity游戏源码分享-植物大战僵尸素材与源码

Unity游戏源码分享-植物大战僵尸素材与源码 完整版本下载地址&#xff1a; https://download.csdn.net/download/Highning0007/88191862

配置Arduino+ESP32走过的巨坑

项目场景&#xff1a; 前几天去淘宝买了块ESP32拿来用&#xff0c;配置Arduino最新版ESP32 2.0.11走过的巨坑。 问题描述 先安装好了ArduinoIDE最新版&#xff08;教程里介绍去官网下&#xff09;&#xff0c;然后配置ESP32开发板&#xff0c;后面发现安装速度惊人。 去找加速…

C语言 ——函数指针变量

1、概念&#xff1a; 数组指针 - 是指针-是指向数组的指针&#xff0c;是存放数组地址的指针 函数指针 - 是指针 是指向函数的指针 - 是存放函数地址的指针!! 如上所示&#xff0c;函数也是具有地址的&#xff0c;而存放函数地址的指针变量成为函数指针变量。 而有如上所示&a…

用python来爬取某鱼的商品信息(1/2)

目录 前言 第一大难题——找到网站入口 曲线救国 模拟搜索 第二大难题——登录 提一嘴 登录cookie获取 第一种 第二种 第四大难题——无法使用导出的cookie 原因 解决办法 最后 出现小问题 总结 前言 本章讲理论&#xff0c;后面一节讲代码 拿来练练手的&#xff…