Mybatis-plus 类型转换的那些坑如何躲避?

不知道你有没有用过mybatis/mybatis-plus?应该都用过吧(碎碎念:没用过我也就很无奈了),那么在用这个半orm框架的时候不知道你们都遇到了哪些坑,今天我就来说说我遇到的坑以及解决方案。
因为在设计数据库的时候使用到了json类型结构要对应Entity的List<Entity>类型,就需要考虑如何完成这个蜜汁操作??
对mybatis有些了解的应该知道实体映射只会自动映射基本类型,像list或者map这种类型是没办法来进行自动映射的,所以很多人在处理的时候常采用以下方案:

将Entity字段类型更改成String类型,让mybatis/mybatis-plus来帮我们映射,映射后的字段值再进行二次处理

不得不说,这是一种方案,但是这种方案相对来说比较麻烦,需要有二次操作。进一步调研发现(相信你们在写的时候也或多或少搞过,就是指定类型,ResultMap中指定字段的typehandler–类型处理器)。不知道你们的sql是写在xml中还是直接使用的wrapper接口来进行的,所以我不会推荐你们去使用xml的方式进行,因为我有尝试网上的各种方法,都为能生效合理,所以我下面主要来说一下注解使用wrapper方式


华丽分隔符之后讲述解决方案,前期准备
在这里插入图片描述
数据库表结构如上图,sql脚本如下:

CREATE TABLE `message` (
  `id` varchar(24) NOT NULL,
  `content` json DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

在执行过程中你可能会爆粗口,奶奶的,为啥不行呢,为啥我的没有json类型呢?因为json这种类型是5.7版本(也成7版本)之后才有的,自己重新建mysql实例吧。
前期准备有了,那么看一下实体的结构吧:

@Data
@EqualsAndHashCode(callSuper = false)
public class Message extends Model<Message> {
    private String id;
    private List<User> content; 
}
@Data
public class User {
    private String id;
    private String name;
    private String nameEn;
    private String avatar;
}

首先我们第一步需要对实体进行修改,修改效果如下:

@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "message",autoResultMap = true)
public class Message extends Model<Message> implements Serializable {
    private String id;
    @TableField(value = "content",typeHandler = FastjsonTypeHandler.class)
    private List<User> content;
}

这里尤其注意autoResultMap注解,默认是false,点进入看到如下:

   /**
    * 是否自动构建 resultMap 并使用,
    * 只生效与 mp 自动注入的 method,
    * 如果设置 resultMap 则不会进行 resultMap 的自动构建并注入,
    * 只适合个别字段 设置了 typeHandler 或 jdbcType 的情况
    *
    * @since 3.1.2
    */
   boolean autoResultMap() default false;

这里如果你开启的自动匹配类型,就必须要给特殊字段设置他的类型转换器,否则就会抛出异常,如下:
在这里插入图片描述
大概的意思就是让你给这个字段设置一个类型转换器,因为mybatis/mybatis-plus不识别list这种类型,当都设置好了之后就可以测试一下了,测试代码如下:

@RestController
@RequestMapping("/message")
public class MessageController {

    private final MessageService messageService;

    public MessageController(MessageService messageService) {
        this.messageService = messageService;
    }

    @GetMapping("get")
    public ResponseEntity<?> get(String id) {
        return CommonResponse.success(messageService.get(id));
    }

    @GetMapping("set")
    public ResponseEntity<?> set() {
        return CommonResponse.success(messageService.set());
    }
}
@Service
public class MessageService {
    private final MessageMapper messageMapper;

    public MessageService(MessageMapper messageMapper) {
        this.messageMapper = messageMapper;
    }

    public Message get(String id) {
        return messageMapper.selectById(id);
    }

    public int set() {
        Message message = new Message();
        message.setId(new ObjectId().toHexString());
        List<User> users = new ArrayList<>();
        User user = new User();
        user.setId(new ObjectId().toHexString());
        user.setName("张三");
        user.setName("zhangsan");
        user.setAvatar("http://www.baidu.com");
        users.add(user);
        message.setContent(users);
        return messageMapper.insert(message);
    }
}
@Mapper
@Repository
public interface MessageMapper extends BaseMapper<Message> {

}

效果如下:
在这里插入图片描述

{
    "code": 200,
    "message": "ok",
    "data": {
        "id": "60434fba268a283401628323",
        "content": [
            {
                "name": "张三",
                "id": "60434fba268a283401628324",
                "avatar": "http://www.baidu.com",
                "nameEn": "zhangsan"
            }
        ]
    }
}

大概的处理流程就是上边,xml方式我曾有过尝试,不知道是因为版本的原因还是因为我操作的原因,不能生效,只有这种方式最直接有效,typehandler也是有很多类型,可以使用fastjson,也可以使用其他的,如果你们还有其他好的方式,可以整理一下甩个链接给我…


坑:
当你使用了某个类型转换器,就必须添加上与这个类型转换器相关的依赖,比如你使用了FastjsonTypeHandler就必须添加上FastJson的依赖,否则不会生效。
另外一个坑就是如果使用FastjsonTypeHandler这种类型转换器,返回的时候上述例子中内层嵌套的List<User>就不再是User对象了,而是被转换成JSONObject对象。如下:
在这里插入图片描述
对直接返回给前端的数据友好,但是如果你还要对查询到的数据当成对象来处理就只能采用:1、自定义类型转换器 2、将JSONObject再转换成实体对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

new_repo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值