# Exclude non-column properties

Three ways:

  • Use transient

    private transient String noColumn;
  • Use static

    private static String noColumn;
  • Use TableField Annotation

    private String noColumn;

# Runtime Exception Invalid bound statement (not found)

No doubt, it's caused by incorrect configuration/environment

  • Check whether the jar confliction

  • Check your scan path for Mapper.java, 2 ways:

    • 1:Add MapperScan on your Configuration class
    public class YourConfigClass{
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer scannerConfigurer = new MapperScannerConfigurer();
        //you can also get the basePackage via environment configuration
        return scannerConfigurer;
  • Check whether @TableId(Primary Key) is specified. If not, methods for ById(such as selectById) will encounter this error. If one of the property named "id", @TableId is optional(MP treat "id" as Primary Key)

  • Check whether MybatisSqlSessionFactory is used, instead of SqlSessionFactory

  • Check whether customized SqlInjector is defined, and getMethodList() is overrided, and your basic methods is added(see DefaultSqlInjector (opens new window), for customized basic methods, see sample (opens new window))

# Customized SQL cannot be executed

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="typeAliasesPackage" value="xxx.entity" />
    <property name="mapperLocations" value="classpath*:/mybatis/*/*.xml"/>
  mapper-locations: classpath*:/mapper/**/*.xml
  • Using IDEA (opens new window): XML files under src/main/java folder will not be compiled to target folder, you can solve it by:

    • Put your xml files under resources folder
    • Or configure pom(for maven project) like below:
              <!-- xml files under /java folder-->
          <!-- xml files under /resources folder(this configuration is optional)-->


Notice!For Maven multiple modules, scan path should start with classpath*: (load xml files from multiple jars)

# Exception For Startup

  • One:

    java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class

    MapperScan should exclude com.baomidou.mybatisplus.mapper.BaseMapper and subclass(such as customized basic mapper), e.g.:

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    public interface SuperMapper<T> extends BaseMapper<T> {
        // your methods
  • Two:

    Injection of autowired

    CAUSE:Spring 3 not support Generic Type Injection. Please upgrade to Spring 4+

  • Three:

    java.lang.NoSuchMethodError: org.apache.ibatis.session.Configuration.getDefaultScriptingLanguageInstance() Lorg/apache/ibatis/scripting/LanguageDriver

    Mybatis Version problem: this method is provided since v_3.4.2, upgrade mybatis version(Manage Mybatis version by MP is recommended)

# Cannot autofill primary key with Long type

Check whether long type is used instead of Long


For long type, default value=0, MP only has null value check

# Javascript precision problem for ID_WORKER

Length of ID_WORKER value is 18-19, which JavaScript cannot process correctly, manifest as last two digits always 0. Ideas: return String instead of Long(can use ID_WORKER_STR for String id)

  • FastJson Serialization


    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastJsonConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fjc = new FastJsonConfig();
        // configure the strategy
  • JackJson Serialization

    • Way 1:

      // Use Annotation
      public long getId() {
          return id;
    • Way 2:

      // Global configuration(for all Long type, will return String instead)
      final ObjectMapper objectMapper = new ObjectMapper();
      SimpleModule simpleModule = new SimpleModule();
      simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
  • General way: Use ID_WORKER_STR type which is for String id, Or add method public String getIdStr() , frontend use idStr

# Set null or empty string value for Insert / Update

  • Use FieldStrategy:

    • IGNORED:All Null/Empty value will be used for CRUD
    • NOT_NULL:Only Not Null value will be used for CRUD. It's used by default
    • NOT_EMPTY:Not Empty value will be used for CRUD.

If you want to update Empty String or null value, you need to adjust FieldStrategy :

  • Way 1:Adjust Global Field Strategy

    Configurate fieldStrategy in GlobalConfiguration

  • Way 2:Adjust entity property Field Strategy

    You can specify the strategy for CURD(Refer to @TableField):

    @TableField(insertStrategy=FieldStrategy.NOT_EMPTY, updateStrategy=FieldStrategy.IGNORED, whereStrategy=FieldStrategy.NOT_EMPTY)
  • Way 3:Use UpdateWrapper (3.x)


       new User().setName("mp").setAge(3),
               .set(User::getEmail, null) //set email=null
               .eq(User::getId, 2)
    //or put the set value in Wrapper.set 
           .set(User::getAge, 3)
           .set(User::getName, "mp")
           .set(User::getEmail, null) //set email=null
           .eq(User::getId, 2)

# Result Type is boolean for Column with type bit, tinyint(1)

Mysql driver will recognize tinyint(1) as boolean: 0=false, other=true

MyBatis doesn't handle such case, if you won't want map tinyint(1) to boolean, you can do:

  • Modify column type from tinyint(1) to tinyint(2) or int
  • or Modify the jdbc connection param, add tinyInt1isBit=false:

# Two limit statement in running SQL

CAUSE: 2 PaginationInterceptor configured. Check your configuration and keep one only

# Return Primary Key after Insert

Primary Key will be set to Entity.id property, just use getId() to get it

# Specify select columns in MP

  • Use EntityWrapper.sqlSelect (v_2.x)
  • Use Wrapper.select() (v_3.x)
//For version 2.x
EntityWrapper<H2User> ew = new EntityWrapper<>();
ew.setSqlSelect("test_id as id, name, age");//only select 3 columns
List<H2User> list = userService.selectList(ew);
for(H2User u:list){
    Assert.assertNull(u.getPrice()); // this column not selected

    .select(User::getId, User::getName)
//or use QueryWrapper
    new QueryWrapper<User>()

# Second Level Cache on Mapper

We suggest to put cache on service level. You can customize your own BaseServiceImpl

If you still want to put cache on mapper level, please use CachePaginationInterceptor to replace PaginationInterceptor

# Refresh Second Level Cache on Mapper

You can use one of the ways below:

  • Add Cache Annotation on Mapper, specify implementation, eviction
public interface DataResourceMapper extends BaseMapper<DataResource>{}
  • Add cache-ref in mapper.xml
<cache-ref namespace="com.your.company.mapper.UserMapper"></cache-ref>

# Cause: org.apache.ibatis.type.TypeException:Error setting null for parameter #1 with JdbcType OTHER

Add configuration: jdbcTypeForNull=NULL

Spring Configuration Bean:

MybatisConfiguration configuration = new MybatisConfiguration();
configuration.setMapUnderscoreToCamelCase(true);//open Underscore to Camel case

Yml Configuration

    jdbc-type-for-null: 'null' 

# Cannot get params from Page object in customized SQL(2.x Only)

MP v_2.x Only: Page extends RowBounds, which is built-in object for Mybatis, cannot get in XML You can use a Map/POJO as param, or use @Param("pages") int pages

# Auto Underscore To Camel Case for return type Map

Only for:resultType="java.util.Map"

  • Spring Boot
public ConfigurationCustomizer configurationCustomizer() {
    return i -> i.setObjectWrapperFactory(new MybatisMapWrapperFactory());

# Use limit in wrapper

// only get one record, for Mysql only
wrapper.last("limit 1");

# Why only Service has insertBatch()

  • SQL has limitation of length, batch sql may exceed; may cause leakage of jdbc connection
  • SQL Batch Grammar different for Databases, cannot make it as a generic solution
  • Current solution for batch: Loop the records for insert, and commit in batch(maybe have a little performance problem)

# Autofill not work for Logic Deletion

  • Autofill is to put the values to entity when do insert/update, but logic deletion method is deleteById(), which the param is the Primary Key, so autofill won't work

  • If you want to enable autofill for logic Deletion:

    • Way 1: use update():UpdateWrapper.set("logicDeleteColumn","deleteValue")
    • Way 2: refer to Sql Injector, use com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill for SQL injection.
      NOTE: Only work for the fields with @TableField(fill=FieldFill.INSERT/UPDATE/INSERT_UPDATE)
  • Java Config Bean for Way 2:

    1. Customize SqlInjector
    public LogicSqlInjector logicSqlInjector(){
        return new LogicSqlInjector() {
             * Inject your own basic methods
            public List<AbstractMethod> getMethodList() {
                List<AbstractMethod> methodList = super.getMethodList();
                methodList.add(new LogicDeleteByIdWithFill());
                return methodList;
    1. Customize your basic mapper
    public interface MyBaseMapper<T> extends BaseMapper<T> {
         * Generic methods
        int deleteByIdWithFill(T entity);

# Deal the KEY WORD of database in 3.x

For 2.x, KEY WORD of database will be recognized and dealt automatically. But this feature is removed from 3.x

  • Mp supports multiple databases, and those databases have different solution for KEY WORD, it's hard for maintenance
  • We don't recommend to use KEY WORD for column name
  • So let user to deal the KEY WORD, for example:
@TableField(value = "`status`")
private String status;

# MybatisPlusException: Your property named "xxx" cannot find the corresponding database column name!

  • Effected version: v_3.1.1+
  • Appearance: Code works fine for Unit Test, but failed for debugging on application server
  • CAUSE: dev-tools, MP use Class Object(User.class) as the Cache Key instead of ClassName for table info cache since v_3.1.1, dev-tools will use different ClassLoader to load the classes, which will cause such problem
  • Solution: remove dev-tools from pom file