ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

S-mall-ssm 通用Mapper原理深度解析:注解+反射+泛型+静态代理如何实现ORM?

S-mall-ssm 通用Mapper原理深度解析:注解+反射+泛型+静态代理如何实现ORM? S-mall-ssm 通用Mapper原理深度解析注解反射泛型静态代理如何实现ORM【免费下载链接】S-mall-ssm小小商城系统JavaWEB项目基于SSM仿天猫页面功能齐全实现了自动处理关联查询的通用Mapper、抽象 BaseService 类、注解鉴权、参数注解校验等项目地址: https://gitcode.com/gh_mirrors/smal/S-mall-ssm很多同学学完 SSMSpring SpringMVC MyBatis后最头疼的就是关联查询查一个分类要手动再查商品、查一个订单要手动拼商品明细代码越写越长逻辑越堆越乱。而S-mall-ssm 通用Mapper给出了一个非常聪明的答案用注解 反射 泛型 静态代理四种技术组合实现了一套轻量级的 ORM 自动关联查询机制。这个仿天猫的SSM商城系统项目small.sql 里包含了完整的建表数据向我们展示了不引入 JPA、不写繁琐的 XML 关联映射照样能让 MyBatis 自动处理一对多、多对一关系。本文将带你从零读懂这套通用Mapper的设计原理理解它是如何把关系数据库翻译成对象世界的。一、先认识 S-mall-ssm一个能跑通全流程的 SSM 商城系统S-mall-ssm 是一个功能非常齐全的 JavaWEB 商城项目首页展示、分类浏览、商品详情、购物车、订单、支付、评论、后台管理一应俱全页面完全仿照天猫风格。它的技术栈是经典的 SSM 三件套但与众不同的是作者在 MyBatis 之上封装了一层通用 Mapper让多表关联这件事变得几乎零成本。下面这张首页横幅就是项目自带的图片素材可以看到商品展示、促销活动等模块都已经实现这套系统不仅能用更值得学习的是它内部的架构设计——尤其是通用 Mapper 的四个核心文件通用 Mapper 核心处理类src/main/java/tmall/mapper/ORM/Mapper4ORM.java静态代理封装类src/main/java/tmall/mapper/ORM/Mapper.javaMapper 工厂src/main/java/tmall/mapper/ORM/MapperFactory.javaPOJO 泛型标记接口src/main/java/tmall/pojo/ORM/POJOMapper.java二、为什么需要通用Mapper先看看原生 MyBatis 的痛点在传统 MyBatis 开发中如果要查询一个商品及其所属分类、再带出商品的图片列表你得手写多表 JOIN 的 SQL或者写多条查询在 Service 层手动调用多个 mapper自己组装对象每次新增关联关系都要改 XML、改 Service 代码。而 S-mall-ssm 的通用 Mapper 实现了查一个对象自动带出它的关联对象。比如后台要展示某分类下的商品只需要一行调用就能拿到完整对象树。这种体验是怎么做到的答案就藏在四种技术的配合里。三、四大核心技术各司其职1. 注解把关系写进 Java 代码S-mall-ssm 在src/main/java/tmall/annotation/ORMAnnotation/包下定义了四个自定义注解注解作用用法示例ManyToOne标记多对一或一对一字段商品对象里的Category字段OneToMany标记一对多字段分类对象里的ListProduct字段JoinColumn指定外键字段名配合上面两个使用指定外键在数据库里的列名Enumerated处理枚举与数据库字符串的互转订单状态枚举字段有了这些注解POJO 就能自述它跟其他对象的关系而 Mapper 层完全不用写关联 SQL。这就是 ORM 的第一步用元数据描述映射。2. 泛型让 POJO 自报家门光有关系注解还不够通用 Mapper 还得知道该去哪个 Mapper 查目标对象。这里用了一个很巧妙的设计——泛型标记接口POJOMapperM每个由 MyBatis Generator 生成的 POJO 都会实现这个接口并在尖括号里写明自己对应的 Mapper。例如Category类就是public class Category extends CategoryExtension implements POJOMapperCategoryMapper { // ... }这样在运行时通过反射读取ParameterizedType参数化类型就能从商品类推导出商品对应的 Mapper 类从而实现按需加载、动态查找这就是泛型在 ORM 中的核心价值。3. 反射运行时读注解、拼查询、塞结果这是整套机制的心脏全部集中在Mapper4ORM.java中。它的工作流程可以概括为三步读注解用getFieldsEquals()扫描对象所有字段包括父类找出带ManyToOne、OneToMany、Enumerated注解的字段拼查询通过JoinColumn拿到外键名再借助泛型推导出目标 Mapper用反射调用 MyBatis 的selectByExample方法查出目标对象塞结果用反射调用对象的 setter 方法把查出来的关联对象填回原对象。整个过程没有写死任何一个表名或类名全部是看到注解 → 反射执行的动态逻辑。这也是为什么这套 Mapper 能通用于项目里的所有实体真正做到一次编写处处通用。4. 静态代理不碰 MyBatis只做拦截增强反射做关联填充还不够优雅因为每次都要手动调用。S-mall-ssm 的解决方案是再包一层——Mapper.java继承了Mapper4ORM对 MyBatis 生成的 mapper 做了静态代理public Object selectByPrimaryKey(Integer id, Integer depth) throws Exception { Object object mapper.getClass().getMethod(selectByPrimaryKey, Integer.class) .invoke(mapper, id); // 先执行真正的查询 fillOnReading(object, depth); // 再自动填充关联对象 return object; }代理方法做的事很简单先调用真实 mapper 完成单表查询再调用填充逻辑补全关联数据。对外层调用方来说感觉就像 MyBatis 原生支持了自动关联查询一样无缝透明。而MapperFactory.java则是装配工厂通过SqlSessionTemplate.getMapper()拿到 MyBatis 的代理对象包装成通用 Mapper 交给 Service 层使用。四、读取流程详解一次查询如何自动捞出整个对象树当 Service 层调用selectByPrimaryKey(id)或selectByExample(example)时通用 Mapper 会进入fillOnReading()递归填充流程依次处理三类关系多对一填充fillManyToOneOnReading读取商品时发现category字段带ManyToOne注解就取出外键cid的值去CategoryMapper查出对应的分类对象塞回来一对多填充fillOneToManyOnReading读取分类时发现products字段带OneToMany就取当前分类的id去ProductMapper查出该分类下所有商品组装成 List 塞回来枚举转换fillEnumOnReading把数据库读出的字符串按Enumerated指定的变量名转成 Java 枚举对象。更贴心的是填充本身还是递归的查出来的商品会继续填充它的分类分类又会填充它的商品……配合深度参数depth默认 2既能拿到多层关联数据又能防止对象循环引用导致死循环这个设计非常精巧。五、写入流程插入和更新时外键与枚举自动就位很多人会忽略写操作其实写入同样是 ORM 的关键一环。fillOnWriting()在 insert / update 之前会做两件预处理枚举转字符串把 Java 枚举对象转成数据库能存的字符串塞回对应的 String 字段多对一外键提取如果对象里带的是完整的关联对象比如整个 Category就从它身上取出id塞回外键字段保证入库的数据是干净的整数外键。这样一来Service 层写数据时只需要关心对象长什么样完全不用手动管理外键细节代码极其清爽。六、往上再抽象一层BaseService 的魔法通用 Mapper 之上项目还封装了抽象的BaseServiceImpl通过继承Service4DAOImpl自动识别泛型、预装载 Mapper。Service 层甚至支持一种声明式查询的写法list(cid, categoryId) // 查该分类下的所有商品 list(name_like, 红米) // 模糊查询 list(pagination, paginationObj) // 分页查询底层会根据参数后缀_like、_gt、pagination、order、depth自动拼出不同的查询条件再交给通用 Mapper 执行。这套变长参数约定的设计把 Service 层从大量样板代码中彻底解放了出来。七、总结这套 ORM 设计的巧妙之处回过头看S-mall-ssm 的通用 Mapper 之所以值得学习是因为它用最简单直白的技术组合实现了非常实用的功能注解负责描述关系What泛型负责定位目标Where反射负责动态执行How静态代理负责无感增强When。对于初学者来说这个项目是理解 ORM 底层原理的绝佳教材——比直接用 JPA/Hibernate 更能看清对象-关系映射的本质。你可以顺着Mapper4ORM.java的fillOnReading和fillOnWriting两个入口逐步阅读再对照Category、Product等 POJO 上的注解很快就能把整条链路串起来。如果你想本地跑起来看看效果克隆仓库后导入 MySQL 的small.sql即可快速初始化数据。希望这篇通用Mapper原理解析能帮你拨开云雾真正看懂这套注解 反射 泛型 静态代理实现的轻量级 ORM。【免费下载链接】S-mall-ssm小小商城系统JavaWEB项目基于SSM仿天猫页面功能齐全实现了自动处理关联查询的通用Mapper、抽象 BaseService 类、注解鉴权、参数注解校验等项目地址: https://gitcode.com/gh_mirrors/smal/S-mall-ssm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表