关于MyBatis-Plus 自动填充处理器的坑

公司持久层框架使用的是Mybatis增强版:Mybatis-Plus,再一次做更新操作时,报了一个错误,由于隔得时间太久,代码也已经进行过改动,所以只有采用其它方式重现一下。

问题再现

首先新建一个表,很简单没什么说的:
在这里插入图片描述
新建一个实体类:

package com.aecc.smart.fire.server.entity;

import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.annotations.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("em_test")
public class EmTest implements Serializable {
    private static final long serialVersionUID = 1L;

    private Long id;

    @TableField("name")
    private String name;

    @TableField("age")
    private int age;
}

然后创建空的service、serviceImpl、mapper:

public interface EmTestService extends IService<EmTest> {

}

@Service
public class EmTestServiceImpl extends ServiceImpl<EmTestMapper, EmTest> implements EmTestService {
}

public interface EmTestMapper extends BaseMapper<EmTest> {
}

新建测试类:

package com.aecc.smart.fire.server;

import com.aecc.smart.fire.server.entity.EmTest;
import com.aecc.smart.fire.server.service.EmTestService;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class EmTest1 {
    @Autowired
    private EmTestService emTestService;

    @Test
    public void insertOrUpdate(){
        String emTestString = "{\n" +
//                "    \"id\": \"1278618408770588673\",\n" +
                "    \"name\": \"lisi\",\n" +
                "    \"age\": 18\n" +
                "}";
        EmTest emTest = JSON.parseObject(emTestString, EmTest.class);
        emTestService.insertOrUpdate(emTest);
        System.out.println("...");
    }
}

执行测试,结果正常,关键输出信息如下:
关于MyBatis-Plus 自动填充处理器的坑_第1张图片
表中多了一条记录:
在这里插入图片描述
再执行更新操作:

package com.aecc.smart.fire.server;

import com.aecc.smart.fire.server.entity.EmTest;
import com.aecc.smart.fire.server.service.EmTestService;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class EmTest1 {
    @Autowired
    private EmTestService emTestService;

    @Test
    public void insertOrUpdate(){
        String emTestString = "{\n" +
                "    \"id\": \"1278623237685329921\",\n" +
                "    \"name\": \"lisi\",\n" +
                "    \"age\": 18\n" +
                "}";
        EmTest emTest = JSON.parseObject(emTestString, EmTest.class);
        emTestService.insertOrUpdate(emTest);
        System.out.println("...");
    }
}

报错了:
关于MyBatis-Plus 自动填充处理器的坑_第2张图片
因为项目里面添加了自动填充处理器:
在这里插入图片描述

package com.aecc.smart.fire.server.config;

import java.util.Date;

import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import com.aecc.smart.fire.server.feign.BaseContextUtils;
import com.baomidou.mybatisplus.mapper.MetaObjectHandler;

/**
 * 自动填充处理器
 * @Description TODO
 * @date 2019年11月14日 下午1:41:10
 */
@Component
public class MyMetaObjectHandler extends MetaObjectHandler{

	@Override
	public void insertFill(MetaObject metaObject) {
		// TODO Auto-generated method stub
		this.setFieldValByName("addTime", new Date(), metaObject);
		this.setFieldValByName("addPerson", BaseContextUtils.getUserID(), metaObject);
		this.setFieldValByName("deleted", 0, metaObject);
	}

	@Override
	public void updateFill(MetaObject metaObject) {
		// TODO Auto-generated method stub
		this.setFieldValByName("lastModifyTime", new Date(), metaObject);
		this.setFieldValByName("lastModifyPerson", BaseContextUtils.getUserID(), metaObject);
	}
	
}

但是添加的时候,实体类没有insertFill方法中执行setFieldValByName方法时不会报错。

分析如下:

首先看BaseMapper:
关于MyBatis-Plus 自动填充处理器的坑_第3张图片
关于MyBatis-Plus 自动填充处理器的坑_第4张图片
updateById方法执行的时候,把entity中字段的值处理成"et_"+字段名来最后填充占位符的值。

MetaObjectHandler中方法:
关于MyBatis-Plus 自动填充处理器的坑_第5张图片
可知,添加的时候在处理不存在字段addTime等时,两个if条件,都不满足,返回this;而更新的时候处理不存在字段lastModifyTime时,会进入到else if判断条件中。原因往下看:
关于MyBatis-Plus 自动填充处理器的坑_第6张图片
在执行MetaObjectHandler的setFieldValByName方法前,MetaObject对象已经处理过,而MetaObject对象中的setValue其实就是给这些字段设置值,并且有一个(“et_”->object对象)的属性->值。
关于MyBatis-Plus 自动填充处理器的坑_第7张图片
最后跟踪到如下方法:
关于MyBatis-Plus 自动填充处理器的坑_第8张图片
关于MyBatis-Plus 自动填充处理器的坑_第9张图片
从HashMap类型的setMethods属性中找propertyName为lastModify就会找不到,进而抛出异常。

解决方式有两个:

  1. 在实体类添加公共字段,数据库表也添加对应字段(不推荐,因为表中本来就不需要这些字段)
  2. 修改的时候,手动写sql

你可能感兴趣的:(java)