SpringMVC结合设计模式:解决MyBatisPlus传递嵌套JSON数据的难题

🎉🎉欢迎光临,终于等到你啦🎉🎉

🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀

🌟持续更新的专栏 《Spring 狂野之旅:从入门到入魔》 🚀

本专栏带你从Spring入门到入魔

这是苏泽的个人主页可以看到我其他的内容哦👇👇

努力的苏泽http://suzee.blog.csdn.net/


引出

我们经常会遇到需要传递对象的场景。有时候,我们需要将一个对象的数据传递给另一个对象进行处理,但是又不希望直接暴露对象的内部结构和实现细节。这时,我们可以使用模板模式来实现优雅的对象传递。

为了实现这个场景,我们可以使用模板模式。

模板模式是一种行为设计模式,它定义了一个抽象类或接口作为模板,其中包含了一个或多个抽象方法,用于定义算法的骨架。具体的子类可以根据需要实现这些抽象方法,从而完成算法的定制化。

说说我这边的起因

大概是这样的 要做一个问卷系统 这个问卷里面包含各种各样的标签和因子 就使得 属性里面又包含属性 对象里面又嵌套数组 数组里面又有对象****遇到这种情况相信大家都会很头疼吧 那这种时候很多人就要开始写Mapper了 这里我提出一个大大节约时间的方法 ++类型构造器++

设计模式的引入

我们知道 每一个属性需要引入一个新的类型构造器 那就要根据他的具体情况重写一个 那岂不是代码量指数级上涨?

还有很多...各种嵌套 于是我想 有没有一种办法能规定好所有的嵌套方法的逻辑 然后他们只需要说明自己是什么类型 就能套进去?

有 就是今天要说的 ++模板方法++

先定义一个通用的模板

java 复制代码
public class JsonArrayHandler<T> extends BaseTypeHandler<List<T>> {

    private Class<T> type;

    public JsonArrayHandler() {
        // 添加无参构造函数
    }
    public JsonArrayHandler(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, JSONArray.toJSONString(parameter));
    }

    @Override
    public List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        String json = rs.getString(columnName);
        return parseJsonArray(json);
    }

    @Override
    public List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        String json = rs.getString(columnIndex);
        return parseJsonArray(json);
    }

    @Override
    public List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        String json = cs.getString(columnIndex);
        return parseJsonArray(json);
    }

    private List<T> parseJsonArray(String json) {
        JSONArray jsonArray = JSONArray.parseArray(json);
        return jsonArray.toJavaList(type);
    }
}

让我逐点解释其妙处:

  1. 泛型支持:public class JsonArrayHandler<T> extends BaseTypeHandler<List<T>> 中的 <T> 表示这是一个泛型类,可以适用于不同类型的 JSON 数组字段。通过使用泛型,可以在运行时指定具体的类型,使得处理不同类型的 JSON 数组变得更加灵活和通用。

  2. 构造函数重载:public JsonArrayHandler() 是一个无参构造函数,而 public JsonArrayHandler(Class<T> type) 是一个有参构造函数。通过提供两个构造函数,可以灵活地创建 JsonArrayHandler 的实例。无参构造函数用于在不知道具体类型时创建实例,而有参构造函数用于在已知类型时创建实例。

  3. 参数设置:setNonNullParameter 方法用于将 Java 对象转换为存储在数据库中的 JSON 字符串。在这里,使用了阿里巴巴的 FastJSON 库将 List<T> 对象转换为 JSON 字符串,并将其设置到 PreparedStatement 对象中。

  4. 结果获取:getNullableResult 方法用于从数据库中获取 JSON 字符串,并将其转换回 List<T> 对象。在这里,使用了 FastJSON 库将 JSON 字符串解析为 JSONArray,然后将其转换为 List<T> 对象。

有了这一个模板 那么剩下来的就是 直接使用他!

这里浅浅给出我业务中的6个例子

  1. 商品分类:数据库中的 category_ids 字段存储了商品所属的分类列表。使用自定义 TypeHandler,可以将 Java 对象的 List<Category> 直接映射到数据库的 JSON 字符串,并在读取时将 JSON 字符串转换回 List<Category>。

    java 复制代码
    public class CategoryHandler extends JsonArrayHandler<Category> {
        public CategoryHandler() {
            super(Category.class);
        }
    }
  2. 用户角色:数据库中的 role_ids 字段存储了用户所拥有的角色列表。使用自定义 TypeHandler,可以将 Java 对象的 List<Role> 直接映射到数据库的 JSON 字符串,并在读取时将 JSON 字符串转换回 List<Role>。

    java 复制代码
    public class RoleHandler extends JsonArrayHandler<Role> {
        public RoleHandler() {
            super(Role.class);
        }
    }
  3. 订单商品列表:数据库中的 order_items 字段存储了订单中的商品列表。使用自定义 TypeHandler,可以将 Java 对象的 List<OrderItem> 直接映射到数据库的 JSON 字符串,并在读取时将 JSON 字符串转换回 List<OrderItem>。

    java 复制代码
    public class OrderItemHandler extends JsonArrayHandler<OrderItem> {
        public OrderItemHandler() {
            super(OrderItem.class);
        }
    }
  4. 图片列表:数据库中的 image_urls 字段存储了一组图片的 URL 列表。使用自定义 TypeHandler,可以将 Java 对象的 List<String> 直接映射到数据库的 JSON 字符串,并在读取时将 JSON 字符串转换回 List<String>。

    java 复制代码
    public class ImageHandler extends JsonArrayHandler<String> {
        public ImageHandler() {
            super(String.class);
        }
    }
  5. 标签列表:数据库中的 tags 字段存储了一组标签。使用自定义 TypeHandler,可以将 Java 对象的 List<Tag> 直接映射到数据库的 JSON 字符串,并在读取时将 JSON 字符串转换回 List<Tag>。

    java 复制代码
    public class TagHandler extends JsonArrayHandler<Tag> {
        public TagHandler() {
            super(Tag.class);
        }
    }
  6. Answer 类是一个答案类,包含了答案内容 answer 和分数 score 两个字段。Questionnaire 类是一个问卷调查类,其中包含了一些字段,包括主键 id、问题编号 qid、答案 answer、问题名称 qname、问题描述 question、标签 tabans。在 ans 字段上,使用了 @TableField 注解,并设置了 typeHandler = AnswerHandler.class,指定了使用 AnswerHandler 这个自定义的 TypeHandler 来处理该字段。

java 复制代码
public AnswerHandler(Class<Answer> type) {
    super(Answer.class);
}
java 复制代码
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("tb_questionnaire")
public class Questionnaire {
    /**
    * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    private int qid;

    private String answer;
    private String qname;
    private String question;
    private String tab;
    @TableField(exist = false,typeHandler = AnswerHandler.class)
    private List<Answer> ans;

    public void setAnswer() {
        this.answer = JSONUtil.toJsonStr(ans);
    }
    public void setAnswerList() {
        this.ans = JSONUtil.toList(answer,Answer.class);
        answer=null;
    }
}

查询

这样就不用写复杂的Mapper 和sql语句 也能轻松查询嵌套的复杂的JSON数据啦

实现效果

这样就形成了复杂的嵌套的数据的自动构造

相关推荐
北冥you鱼3 分钟前
Go flag 包详解:从命令行解析到实战应用
开发语言·后端·golang
月落星还在15 分钟前
Spring MVC 与 Spring Boot:从“手动挡”到“自动驾驶”的进化论,兼谈前后端分离的哲学
spring boot·spring·云原生·mvc
蓝田~28 分钟前
大模型本地部署与远程调用 — 从 API 到 Agent
java·人工智能·claude·claude code
码农进化录35 分钟前
Java 程序员的 AI 进化论 | Spring Boot 接入 OpenAI 的六个坑,全帮你踩了
java·spring boot·openai
她说彩礼65万38 分钟前
Asp.net core 模型绑定
后端·asp.net
用户342323237631742 分钟前
BLE 传感器节点实战
后端
疯狂成瘾者44 分钟前
Java 常见集合方法
java·windows·python
从此以后自律1 小时前
ConcurrentHashMap 超详细详解
java
fliter1 小时前
Go 1.26 新增 `bytes.Buffer.Peek`:只看数据,不移动读取位置
后端
羑悻1 小时前
我受够了 Coding Agent 的“假聪明,真串行”,于是做了 Meta-Orchestrator!
后端