当前位置: 首页 > ai >正文

【沉浸式解决问题】基于泛型递归,Java中实体类基类开启MybatisPlus的ActiveRecord模式

目录

  • 一、问题描述
  • 二、场景还原
    • 1. 实体类基类 BaseEntity.class
    • 2. 测试实体类 TestTemplate.class
    • 3. 测试类 EntityTests.class
  • 三、原因分析
  • 四、解决方案
    • 1. 实体类基类 BaseEntity.class
    • 2. 测试实体类 TestTemplate.class
    • 3. 测试类 EntityTests.class
  • 五、泛型递归

一、问题描述

MybatisPlus的ActiveRecord模式对本地数据处理项目十分的便捷,同时为了更好的管理公共字段,又引入了BaseEntity作为基类,包括创建时间、创建者、更新时间、更新者等字段,之后所有的实体类再继承基类,但是这样实体类就无法再使用MybatisPlus的Model类提供的数据库操作方法了,想到了通过泛型递归来解决。
在这里插入图片描述


二、场景还原

所有类只保留最简单代码

1. 实体类基类 BaseEntity.class

public class BaseEntity extends Model<T> {
}

2. 测试实体类 TestTemplate.class

public class TestTemplate extends BaseEntity {
}

3. 测试类 EntityTests.class

@SpringBootTest
public class EntityTests {@Testvoid test1() {TestTemplate testTemplate = new TestTemplate();List<TestTemplate> testTemplates = testTemplate.selectAll();}
}

三、原因分析

因为是BaseEntity继承的Model类,所以相关方法也是绑定在BaseEntity上的,TestTemplate作为BaseEntity的子类调用父类的方法,返回的当然应该是父类的类型。而MybatisPlus提供的方法实际上是在Model中的,所以要想办法把子类送到Model的泛型中。


四、解决方案

这里就需要用到Java的一种语法糖,我把它叫做泛型递归,没查到专业的名称,或者叫泛型的泛型也很合适。
上面说到了要把子类送到Model的泛型中,Java又不支持多继承,我的需求又需要继承BaseEntity,那很自然的就想到给BaseEntity一个泛型,再传到Model的泛型中。

1. 实体类基类 BaseEntity.class

public class BaseEntity<T extends BaseEntity<T>>  extends Model<T> {
}

2. 测试实体类 TestTemplate.class

public class TestTemplate extends BaseEntity<TestTemplate> {
}

3. 测试类 EntityTests.class

@SpringBootTest
public class EntityTests {@Testvoid test1() {TestTemplate testTemplate = new TestTemplate();List<TestTemplate> testTemplates = testTemplate.selectAll();}
}

这时候返回类型就正确了
在这里插入图片描述

五、泛型递归

这里再结合BaseEntity<T extends BaseEntity<T>> extends Model<T>详细讲解一下泛型递归这个概念

前面我们决定了要给BaseEntity带一个泛型,那就变成了BaseEntity<T>
什么样的泛型呢,那得是BaseEntity的子类,那就变成了BaseEntity<T extends class<?>
这里引申出第一个问题,继承谁,你可能直接会想到那当然是BaseEntity,那为什么不能是Model呢,语法上是可以的,相当于BaseEntity的泛型允许别的Model的子类代入,比方说其他基类,但实际中我想不到会有这样的极端情况,继承BaseEntity就好,那就变成了BaseEntity<T extends BaseEntity<?>
第二个问题,泛型的要求还有什么,这就是子尖括号里面的问号了,<?>表示任何BaseEntity的子类都可以,而<T>表示只能填当前子类自身。通过刚刚的分析我们可以看出来,<?>无法保证返回的类型,谁知道父类又继承了什么,泛型方法最终返回什么,但<T>可以确保类型一致性,比较适合链式调用、Builder模式、ORM基类等场景,通常也都用这个。

为什么会考虑这个呢,因为Model就是用的<?>

package com.baomidou.mybatisplus.extension.activerecord;import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;public abstract class Model<T extends Model<?>> extends AbstractModel<T> {public Model() {}public SqlRunner sql() {return new SqlRunner(this.entityClass);}
}

再举一个标准的例子,我们常用到的枚举类

public abstract class Enum<E extends Enum<E>>implements Comparable<E>, Serializable {
}

喜欢的点个关注吧><!祝你永无bug!

/*_ooOoo_o8888888o88" . "88(| -_- |)O\  =  /O____/`---'\____.'  \\|     |//  `./  \\|||  :  |||//  \/  _||||| -:- |||||-  \|   | \\\  -  /// |   || \_|  ''\---/''  |   |\  .-\__  `-`  ___/-. /___`. .'  /--.--\  `. . __."" '<  `.___\_<|>_/___.'  >'"".| | :  `- \`.;`\ _ /`;.`/ - ` : | |\  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^佛祖保佑       永无BUG
*/
http://www.xdnf.cn/news/9122.html

相关文章:

  • PID控制学习(位置式,增量式,算法优化,多环串级PID)
  • LitCTF 2025 Robbie Wanna Revenge
  • 并发的产生及对应的解决方案之实例举证
  • Java 中经常犯的错误
  • 2025年5月26日第一轮
  • 【springboot项目部署】打包部署
  • 矩阵链乘法问题
  • vae 视频截图 复习 gans和vae的原理区别
  • JVM垃圾回收器详细介绍
  • 注解的使用和自定义
  • Composer 常规操作说明与问题处理
  • 【部署】读取制度类txt文件导入dify的父子分段知识库
  • Kubernetes 1.33您需要了解的和升级新功能
  • 爬虫学习-Scrape Center spa6 超简单 JS 逆向
  • 二叉树遍历
  • 打破壁垒:国内软件业产品与技术割裂困局及工程师产品思维重塑
  • 无网络docker镜像迁移
  • OSC协议简介、工作原理、特点、数据的接收和发送
  • 5月26日day37打卡
  • 【大模型Pre-Training实战总结】实现Qwen3增量预训练,Lora训练与合并
  • 修改mysql 数据库密码记录
  • MySQL数据库零基础入门教程:从安装配置到数据查询全掌握
  • 2025年AIR SCI1区TOP,具有新变异策略和外部存档机制mLSHADE-SPACMA+数值优化与点云配准,深度解析+性能实测
  • 【2025】harbor仓库搭建
  • MAR:无需量化的掩码自回归图像生成模型
  • Windows Server 2016 下封禁端口规避高危漏洞的测试实践
  • 通过chrome插件自动生成博客评论,高效发外链
  • 15.2【基础项目】使用 TypeScript 实现密码显示与隐藏功能
  • wsl2 安装 nodejs
  • 人工智能与教育科技:2025年个性化学习的新模式