探索ORM宇宙:MyBatis-Plus的力量

news2024/11/16 16:00:16

**技术派项目源码地址 : **

  • **Gitee : 技术派 - https://gitee.com/itwanger/paicoding
  • **Github : 技术派 - https://github.com/itwanger/paicoding

**Mybatis-Plus 官网 : **MyBatis-Plus 🚀 为简化开发而生 (baomidou.com)
image.png

整合Mybatis-Plus

引入依赖
<mybaits-plus.version>3.5.2</mybaits-plus.version>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${mybaits-plus.version}</version>
</dependency>
使用 @MapperScan 注解扫描 mapper 文件
  • **如果Mapper包统一管理 可以直接在启动类加 @MapperScan **
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}
  • 如果不是统一管理就单独写一个配置Config来扫Mapper包
@Configuration
@ComponentScan("com.github.paicoding.forum.service")
@MapperScan(basePackages = {
        "com.github.paicoding.forum.service.article.repository.mapper",
        "com.github.paicoding.forum.service.user.repository.mapper",
        "com.github.paicoding.forum.service.comment.repository.mapper",
        "com.github.paicoding.forum.service.config.repository.mapper",
        "com.github.paicoding.forum.service.statistics.repository.mapper",
        "com.github.paicoding.forum.service.notify.repository.mapper",})
public class ServiceAutoConfig {
}
修改配置文件application.yml
mybatis-plus:
  configuration:
    #开启下划线转驼峰
    map-underscore-to-camel-case: true

MyBatis-Plus 的基本使用

Service CRUD
@Repository
public class TagDao extends ServiceImpl<TagMapper, TagDO> {
  1. @Repository 注解:这是 Spring 提供的注解,用于标识这个类是一个数据访问层(DAO)组件。Spring 会自动扫描并将其实例化为一个 Bean,方便在其他类中通过依赖注入(DI)使用。

  2. ServiceImpl<TagMapper, TagDO>:ServiceImpl 是 MyBatis-Plus 提供的一个抽象类,提供了通用的 CRUD 方法。泛型参数 <TagMapper, TagDO> 意味着 TagDao 类主要用于处理 TagDO 数据对象的数据库操作,并使用 TagMapper 接口定义的方法进行操作。

  3. 通过继承 ServiceImpl 类,TagDao 就可以使用 MyBatis-Plus 提供的通用 CRUD 方法,如 save、getById、updateById 等。这些方法已经实现了基本的数据库操作,通常无需自己编写 SQL 语句。

image.png

@Data
@EqualsAndHashCode(callSuper = true)
@TableName("tag")
public class TagDO extends BaseDO {
    private static final long serialVersionUID = 3796460143933607644L;

    /**
     * 标签名称
     */
    private String tagName;

    /**
     * 标签类型:1-系统标签,2-自定义标签
     */
    private Integer tagType;

    /**
     * 状态:0-未发布,1-已发布
     */
    private Integer status;

    /**
     * 是否删除
     */
    private Integer deleted;
}
  1. @Data 注解是 Lombok 提供的,用于自动生成类的 getter、setter、equals、hashCode 和 toString 方法,简化了代码编写。

  2. @EqualsAndHashCode(callSuper = true) 注解也是 Lombok 提供的注解,callSuper = true 表示要调用父类(BaseDO)的 equals 和 hashCode 方法。

  3. @TableName(“tag”) 注解是 MyBatis-Plus 提供的注解,用于指定数据库表名。

  4. BaseDO 是我们自定义的 DO 基类,实现了 Serializable 接口,并且定义了主键 id(@TableId(type = IdType.AUTO) 表示自增长,是 MyBatis-Plus 提供的注解),创建时间 createTime 和更新时间 updateTime。

@Data
public class BaseDO implements Serializable {

    @TableId(type = IdType.AUTO)
    private Long id;

    private Date createTime;

    private Date updateTime;
}
Mapper CRUD
  • 技术派中一些特殊的增删改查是通过 MyBatis-Plus 的 Mapper CRUD 接口实现的。
public interface ArticleDetailMapper extends BaseMapper<ArticleDetailDO> {
}
@Repository
public class ArticleDao extends ServiceImpl<ArticleMapper, ArticleDO> {
    @Resource
    private ArticleDetailMapper articleDetailMapper;
    
    public Long saveArticleContent(Long articleId, String content) {
        ArticleDetailDO detail = new ArticleDetailDO();
        detail.setArticleId(articleId);
        detail.setContent(content);
        detail.setVersion(1L);
        articleDetailMapper.insert(detail);
        return detail.getId();
    }
}
  • 它继承自 MyBatis-Plus 的 BaseMapper 接口。
public interface BaseMapper<T> extends Mapper<T> {

    /**
     * 插入一条记录
     *
     * @param entity 实体对象
     */
    int insert(T entity);
    
    /**
     * 根据 entity 条件,删除记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
    
    /**
     * 根据 whereEntity 条件,更新记录
     *
     * @param entity        实体对象 (set 条件值,可以为 null)
     * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
    
    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    T selectById(Serializable id);
}
常用注解

@TableName:用于指定数据库表名,通常在实体类(DO 或 Entity)上使用。

@TableName("user")

@TableId:用于指定表中的主键字段。通常在实体类的主键属性上使用。

@TableId(value = "id", type = IdType.AUTO)

其中 value 表示主键字段名,type 表示主键生成策略。

@TableField:用于指定表中的非主键字段。可以用于实体类的属性上,以映射属性和数据库字段。

@TableField(value = "user_name", exist = true)

其中 value 表示数据库中的字段名,exist 表示该字段是否存在(默认为 true)。

@TableLogic:用于指定逻辑删除字段。指在数据库中标记某个记录已删除,而不是真正地删除记录。

@TableLogic(value = "0", delval = "1")

其中 value 表示未删除状态的默认值,delval 表示删除状态的值。

@Version:指定乐观锁字段。乐观锁是一种并发控制策略,解决多个线程同时修改同一条记录的问题。

@Version 
private Integer version

@EnumValue:用于指定枚举类型字段的映射。

@EnumValue 
private Integer status

@InterceptorIgnore:用于忽略 Mybatis-Plus 拦截器的处理。

@InterceptorIgnore(tenantLine = "true") // 表示忽略多租户拦截器。

MyBatis-Plus 查询方法

普通查询
  • 先注入对应Mapper
@Autowired
private ArticleTagDao articleTagDao;
ArticleDO article = articleTagDao.selectById(articleId);
articleTagDao.selectBatchIds(Arrays.asList(1,2));
Map<String, Object> map = new HashMap<>();
map.put("id", 15L);
List<ArticleDO> dtoList = baseMapper.selectByMap(map);
条件构造器 wrapper 查询

MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。

☁️ 条件构造器 | Mybatis-Plus

假如我们来查询这样一个结果,包含“j”且状态是已发布的标签。我们可以这样来构建条件构造器:

@Test
public void testWrapper() {
    QueryWrapper<TagDO> wrapper = new QueryWrapper<>();
    // 包含“j”且状态是已发布
    wrapper.like("tag_name", "j").eq("status", 1);
    BaseMapper<TagDO> baseMapper = tagDao.getBaseMapper();
    List<TagDO> tagList = baseMapper.selectList(wrapper);
    tagList.forEach(System.out::println);
}
  • 通过表的字段总感觉很不舒服,万一哪天数据库表发生变化怎么办呢?代码和数据库就不匹配了呀。
  • 更优雅的做法是采用 Lambda 的方式,技术派中的条件构造器就用的这种方式。

public List<ArticleDO> listArticles(PageParam pageParam) {
    return lambdaQuery()
            .eq(ArticleDO::getDeleted, YesOrNoEnum.NO.getCode())
            .last(PageParam.getLimitSql(pageParam))
            .orderByDesc(ArticleDO::getId)
            .list();
}

MyBatis-Plus 自定义 SQL

  • 在 Mapper 接口中编写自定义 SQL 方法,并使用注解添加自定义的 SQL 语句。
  • 方法参数 accountId 使用了 @Param 注解,指定了参数在 SQL 语句中的名称为 account_id。
  • 这样,在执行 SQL 语句时,MyBatis 会将参数值替换到对应的位置上。
public interface UserMapper extends BaseMapper<UserDO> {
    /**
     * 根据三方唯一id进行查询
     */
    @Select("select * from user where third_account_id = #{account_id} limit 1")
    UserDO getByThirdAccountId(@Param("account_id") String accountId);
}
  • 除此之外,技术派中还使用了 xml 的方式,用来定义一些复杂的 SQL。
  • 在 resources 目录下的好处是,MyBatis-Plus 默认帮我们配置了 xml 的位置。
  • 这样我们就不需要在 application.yml 中再配置了。
public interface RequestCountMapper extends BaseMapper<RequestCountDO> {

    /**
     * 获取 PV 总数
     *
     * @return
     */
    Long getPvTotalCount();

    /**
     * 获取 PV 数据列表
     * @param day
     * @return
     */
    List<StatisticsDayDTO> getPvDayList(@Param("day") Integer day);

    /**
     * 获取 UV 数据列表
     *
     * @param day
     * @return
     */
    List<StatisticsDayDTO> getUvDayList(@Param("day") Integer day);
}
<?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.github.paicoding.forum.service.statistics.repository.mapper.RequestCountMapper">

    <select id="getPvTotalCount" resultType="java.lang.Long">
        select sum(cnt) from request_count
    </select>

    <select id="getPvDayList" resultType="com.github.paicoding.forum.api.model.vo.statistics.dto.StatisticsDayDTO">
        SELECT sum(cnt) as count, date
        FROM request_count
        group by date order by date asc
        limit #{day};
    </select>

    <select id="getUvDayList" resultType="com.github.paicoding.forum.api.model.vo.statistics.dto.StatisticsDayDTO">
        SELECT count(*) as count, date
        FROM request_count
        group by date order by date asc
        limit #{day};
    </select>

</mapper>
  • 该 XML 文件定义了一个 RequestCountMapper 的映射器, 与 RequestCountMapper 相匹配。
  • 它包含了三个自定义查询:getPvTotalCount、getPvDayList 和 getUvDayList。

MyBatis-Plus 更新和删除

更新操作
  • 普通更新 : 直接调用 Service 的 updateById 方法,也就是根据 ID 更新
public void saveTag(TagReq tagReq) {
    TagDO tagDO = ArticleConverter.toDO(tagReq);
    if (NumUtil.nullOrZero(tagReq.getTagId())) {
        tagDao.save(tagDO);
    } else {
        tagDO.setId(tagReq.getTagId());
        tagDao.updateById(tagDO);
    }
}
  • 也可以通过 xml 的形式,当批量修改消息的状态时,技术派是通过这种方式更新的
void updateNoticeRead(@Param("ids") List<Long> ids);
<update id="updateNoticeRead">
    update notify_msg set `state` = 1 where `id` in
    <foreach collection="ids" open="(" close=")" separator="," item="id" index="index">
        #{id}
    </foreach>
</update>
删除操作

技术派中的删除都是逻辑删除,不是物理删除,就是修改 delete 字段,而不是真的把记录从表里删除,所以,最终调用的还是 update 方法,比如说删除文章。

public void deleteArticle(Long articleId, Long loginUserId) {
    ArticleDO dto = articleDao.getById(articleId);
    if (dto != null && !Objects.equals(dto.getUserId(), loginUserId)) {
        // 没有权限
        throw ExceptionUtil.of(StatusEnum.FORBID_ERROR_MIXED, "请确认文章是否属于您!");
    }

    if (dto != null && dto.getDeleted() != YesOrNoEnum.YES.getCode()) {
        dto.setDeleted(YesOrNoEnum.YES.getCode());
        articleDao.updateById(dto);

        // 发布文章删除事件
        SpringUtil.publishEvent(new ArticleMsgEvent<>(this, ArticleEventEnum.DELETE, articleId));
    }
}

MyBatis-Plus 主键策略

主键自增策略
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("category")
public class CategoryDO extends BaseDO {

    private static final long serialVersionUID = 1L;

    /**
     * 类目名称
     */
    private String categoryName;

    /**
     * 状态:0-未发布,1-已发布
     */
    private Integer status;

    /**
     * 排序
     */
    @TableField("`rank`")
    private Integer rank;

    private Integer deleted;
}
  • BaseDO 为 MyBatis-Plus 提供的基类,
  • 内部的 id 字段已经添加了 @TableId(type = IdType.AUTO) 注解。
@Data
public class BaseDO implements Serializable {

    @TableId(type = IdType.AUTO)
    private Long id;

    private Date createTime;

    private Date updateTime;
}
无主键策略
  • 不使用任何主键生成策略,主键值需要手动设置。
public class User {
    @TableId(type = IdType.NONE)
    private Long id;
    // ...
}
UUID主键策略
  • 插入数据时,MyBatis-Plus 会自动生成一个 UUID 值作为主键值。
public class User {
    @TableId(type = IdType.UUID)
    private String id;
    // ...
}
雪花算法主键策略
  • 雪花算法生成分布式唯一 ID
public class User {
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    // ...
}

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

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

相关文章

Flink之SQL client使用案例

Flink的执行模式有以下三种: 前提是我们已经开启了yarnsession的进程&#xff0c;在下图中可以看到启动的id也就是后续任务需要通过此id进行认证&#xff0c;以及任务分配的master主机。 这里启动时候会报错一个ERROR&#xff1a;org.apache.flink.shaded.curator.org.apache…

风电场风机安全监测系统解决方案

建设背景 随着风电产业的快速发展&#xff0c;风力发电已成为一种重要的清洁能源形式。风电场中的风塔是支撑风力发电机组的重要结构&#xff0c;其安全稳定运行对于风电场的正常运营和发电效率至关重要。然而&#xff0c;风塔常常面临风载、震动、腐蚀等多种外部因素的影响&a…

一键切换全球优质Linux 系统软件源及 Docker 源,轻松安装 Docker —— 适配广泛、零门槛、超强功能的开源脚本!

概述 linuxMirrors开源脚本为 GNU/Linux 系统用户提供了强大的工具,帮助用户轻松更换系统软件源并安装 Docker。脚本适配了多种国内外镜像站,经过测试具备良好的下载速度和 IPv6 兼容性,并且还包括了中国大陆教育网镜像站的选项。无需技术背景,文档提供了详尽的操作指引和常…

telegraf、influxdb、grafana安装配置及后端监听器操作

InfluxDB&#xff08;时序数据库&#xff09;&#xff0c;常用的一种使用场景&#xff1a;监控数据统计。 grafana&#xff0c;用作监控页面的前端展示。 telegraf&#xff0c;数据采集器。 ITG及快捷启动百度网盘&#xff1a;百度网盘 链接: 提取码: 0000 其他地址链接&am…

pycharm2023.1破解

下载解压文件&#xff0c;文件夹 /jetbra 复制电脑某个位置 注意&#xff1a; 补丁所属文件夹需单独存放&#xff0c;且放置的路径不要有中文与空格&#xff0c;以免 Pycharm 读取补丁错误。 点击进入 /jetbra 补丁目录&#xff0c;再点击进入 /scripts 文件夹&#xff0c;双…

JAVA中的网络编程巨详解(2w字)

在学习 Java 网络编程之前&#xff0c;我们先来了解什么是计算机网络。 计算机网络是指两台或更多的计算机组成的网络&#xff0c;在同一个网络中&#xff0c;任意两台计算机都可以直接通信&#xff0c;因为所有计算机都需要遵循同一种网络协议。 下面是一张简化的网络拓扑图…

【Unity开发】几种空值判断的性能测试

【Unity开发】几种空值判断的性能测试&#xff09; 项目优化过程中&#xff0c;一个非常细节的优化&#xff0c;就是在项目数据处理过程中&#xff0c;会用大量的null和“”空值的判断&#xff0c;参考了一些网友说的性能差别很大&#xff0c;是不是真的需要优化的问题&#xf…

Kafka【一】Windows下安装单节点Kafka

① 下载 下载软件安装包&#xff1a;kafka_2.12-3.6.1.tgz&#xff0c;下载地址&#xff1a;https://kafka.apache.org/downloads 这里的3.6.1&#xff0c;是Kafka软件的版本。截至到2023年12月24日&#xff0c;Kafka最新版本为3.6.1。2.12是对应的Scala开发语言版本。Scala2…

html+css+js实现盒子

效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>禁止打开盖子</title><style>* {box-sizing: border-box;-webkit-font-smoothing: antialiased;t…

OAuth2-0协议安全学习

有一个问题困扰了很久很久&#xff0c;翻来覆去无法入眠&#xff0c;那就是OAuth2.0有什么安全问题啊 OAuth2.0是一种常用的授权框架&#xff0c;它使网站和 Web 应用程序能够请求对另一个应用程序上的用户帐户进行有限访问&#xff0c;在全世界都有广泛运用 OAuth2.0简介 O…

pygame开发课程系列(6): 游戏优化与发布

第六章 游戏优化与发布 在游戏开发过程中&#xff0c;优化性能和正确发布是至关重要的步骤。本章将探讨如何提升游戏性能&#xff0c;以及如何将游戏打包成独立的可执行文件&#xff0c;以便于分发和使用。 6.1 性能优化 优化游戏性能可以提升用户体验&#xff0c;确保游戏…

非标零部件加工:满足个性化需求的关键

在现代制造业中&#xff0c;非标零部件加工正逐渐成为满足个性化需求的关键环节。随着各行各业对产品独特性和定制化的要求不断提高&#xff0c;传统的标准零部件已经无法完全满足市场的多样化需求。时利和将分享关于非标零部件加工是如何满足个性化需求的。 非标零部件加工的核…

如何恢复火狐浏览器中丢失的书签记录?

如何恢复火狐浏览器中丢失的书签记录&#xff1f; 在数字时代&#xff0c;网络浏览器不仅是获取信息的窗口&#xff0c;更承载着个人习惯与数据&#xff0c;火狐浏览器&#xff08;Firefox&#xff09;以其强大的自定义功能和对用户隐私的重视而广受欢迎&#xff0c;书签的丢失…

资深研发的心愿:PostgreSQL未来若能加入这些功能,将更臻完善

我们已经与 PostgreSQL 和其他数据库一起工作了一段时间。在数据库管理领域&#xff0c;PostgreSQL 以其稳健性和灵活性脱颖而出。然而&#xff0c;随着开发人员在现代应用程序开发的复杂性中航行&#xff0c;还有一些额外功能可以简化他们的工作流。以下是我希望 PostgreSQL 具…

18Canvas 组件

18 Canvas 组件 Tkinter 的 Canvas 组件是一个灵活的绘图区域&#xff0c;允许我们在其中绘制图形、文本和图像。它支持各种绘图操作&#xff0c;如画线、画矩形、画圆形等。 Canvas 组件属性 width 和 height: Canvas的宽度和高度&#xff0c;可以是像素值或以字符为单位。…

【C++】unordered_set和unordered_map的封装(哈希)

&#x1f308;个人主页&#xff1a;秦jh_-CSDN博客&#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/qinjh_/category_12575764.html?spm1001.2014.3001.5482 ​ 目录 key和pair 仿函数hash 迭代器 operator HashTable.h my_unordered_map.h my_unordered_se…

【自动驾驶】控制算法(一)绪论与前期准备

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

白盒测试-发送请求

发送请求-怎么操作&#xff1f; 先创建发送请求对象mockmvc--用mockmvc对象发送请求&#xff08;包含请求url,请求头&#xff0c;请求参数等&#xff09; 用到的源码是mockmvc源码--其中perform方法&#xff0c;他的入参是接口类 用mockmvc对象发送请求&#xff0c;代码是mock…

【机器学习第11章——特征选择与稀疏学习】

机器学习第11章——特征选择与稀疏学习 11.特征选择与稀疏学习11.1子集搜索与评价子集搜索子集评价 11.2 过滤式选择11.3 包裹式选择11.4 嵌入式选择11.5 稀疏表示与字典学习稀疏表示字典学习 11.6 压缩感知 11.特征选择与稀疏学习 11.1子集搜索与评价 特征&#xff1a;描述物…

全国计算机二级Python学习笔记

格式化操作符辅助指令: 格式化输出16进制&#xff0c;十进制&#xff0c;八进制整数 %x — hex 十六进制 %d — dec 十进制 %o — oct 八进制 turtle.setup()函数用于启动一个图形窗口&#xff0c;它有四个参数 turtle.setup(width, height, startx, starty) 分别是&…