Backend Development 16 min read

Advanced MyBatis-Plus Features: Batch Insert, Logical Delete, Auto Field Fill, Type Handlers, Dynamic Table Names, Multi-Tenant

The article demonstrates advanced MyBatis‑Plus techniques—including high‑speed batch inserts with rewriteBatchedStatements, logical deletes via global config, automatic timestamp and user fields through MetaObjectHandler, JSON serialization with JacksonTypeHandler, dynamic table naming via an interceptor, and a brief multi‑tenant overview—to streamline development and reduce boilerplate code.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Advanced MyBatis-Plus Features: Batch Insert, Logical Delete, Auto Field Fill, Type Handlers, Dynamic Table Names, Multi-Tenant

Continuation of a MyBatis-Plus introductory tutorial, showing how to create the tb_user table and the corresponding User entity.

CREATE TABLE `tb_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_no` varchar(255) NOT NULL COMMENT '编号',
  `nickname` varchar(255) DEFAULT NULL COMMENT '昵称',
  `email` varchar(255) DEFAULT NULL COMMENT '邮箱',
  `phone` varchar(255) NOT NULL COMMENT '手机号',
  `gender` tinyint(4) NOT NULL DEFAULT '0' COMMENT '性别  0:男生   1:女生',
  `birthday` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '出生日期',
  `is_delete` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标志 0:否  1:是',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
  `update_by` bigint(20) DEFAULT NULL COMMENT '更新人',
  `address` varchar(1024) DEFAULT NULL COMMENT '地址',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

Entity class definition with Lombok annotations and @TableName .

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "tb_user")
public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String userNo;
    private String nickname;
    private String email;
    private String phone;
    private Integer gender;
    private Date birthday;
    private Integer isDelete;
    private Date createTime;
    private Date updateTime;
    private Long createBy;
    private Long updateBy;
}

1. Batch Insert – performance comparison between mapper‑level loop insert and service‑level saveBatch . Without JDBC rewriteBatchedStatements the mapper takes ~42 s, service ~19 s; after adding rewriteBatchedStatements=true the service batch completes in ~1.3 s.

@Test
public void testMapperBatchAdd() {
    List
users = new ArrayList<>();
    for (long i = 1; i <= 1000; i++) {
        User user = User.builder()
            .id(i)
            .userNo("No-" + i)
            .nickname("哈哈")
            .phone("12345678901")
            .email("[email protected]")
            .birthday(new Date())
            .gender(0)
            .isDelete(0)
            .build();
        users.add(user);
    }
    long start = System.currentTimeMillis();
    users.forEach(userDAO::insert);
    long end = System.currentTimeMillis();
    System.out.println("执行时长:" + (end - start) + "毫秒");
}
@Test
public void testServiceBatchAdd() {
    List
users = new ArrayList<>();
    for (long i = 1; i <= 1000; i++) {
        User user = User.builder()
            .id(i)
            .userNo("No-" + i)
            .nickname("哈哈")
            .phone("12345678901")
            .email("[email protected]")
            .birthday(new Date())
            .gender(0)
            .isDelete(0)
            .build();
        users.add(user);
    }
    long start = System.currentTimeMillis();
    userService.saveBatch(users);
    long end = System.currentTimeMillis();
    System.out.println("执行时长:" + (end - start) + "毫秒");
}

JDBC URL must contain rewriteBatchedStatements=true for high‑performance batch inserts.

2. Logical Delete – global configuration and example of a logical delete operation.

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: isDelete   # field name
      logic-delete-value: 1          # deleted flag
      logic-not-delete-value: 0      # not deleted flag
@Test
public void testLogicDelete() {
    userDAO.deleteById(1L);
}

Query automatically adds is_delete=0 condition.

@Test
public void testQuery() {
    User user = userDAO.selectById(1L);
}

3. Default Field Fill – BaseDO with createTime , updateTime , createBy , updateBy and a MetaObjectHandler implementation that populates these fields automatically.

@Data
public class BaseDO implements Serializable {
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    @TableField(fill = FieldFill.INSERT)
    private Long createBy;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateBy;
}
public class DefaultDBFieldHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        if (metaObject.getOriginalObject() instanceof BaseDO) {
            BaseDO base = (BaseDO) metaObject.getOriginalObject();
            Date now = new Date();
            if (base.getCreateTime() == null) base.setCreateTime(now);
            if (base.getUpdateTime() == null) base.setUpdateTime(now);
            base.setCreateBy(1001L);
            base.setUpdateBy(1002L);
        }
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        Object modifyTime = getFieldValByName("updateTime", metaObject);
        if (modifyTime == null) {
            setFieldValByName("updateTime", new Date(), metaObject);
        }
        Object modifier = getFieldValByName("updateBy", metaObject);
        if (modifier == null) {
            setFieldValByName("updateBy", 1002L, metaObject);
        }
    }
}

4. Field Type Handling – storing a complex JSON object ( Address ) in a varchar column using JacksonTypeHandler .

@Data
public class Address {
    private Long id;
    private String province;
    private String city;
    private String region;
    private String address;
}
@TableField(typeHandler = JacksonTypeHandler.class)
private Address address;

Insert and query examples demonstrate automatic JSON serialization/deserialization.

@Test
public void testTypeHandler() {
    Address address = new Address();
    address.setId(1L);
    address.setProvince("浙江省");
    address.setCity("杭州市");
    address.setRegion("余杭区");
    address.setAddress("城北万象城");
    User user = User.builder()
        .id(100L)
        .userNo("No-001")
        .nickname("哈哈")
        .phone("12345678901")
        .email("[email protected]")
        .birthday(new Date())
        .gender(0)
        .isDelete(0)
        .address(address)
        .build();
    userDAO.insert(user);
}

5. Dynamic Table Name – MyBatis‑Plus interceptor configuration and a TableNameHandler that selects a table suffix based on a request parameter.

@Bean
public MybatisPlusInterceptor paginationInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
    return interceptor;
}

@Bean
public DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
    DynamicTableNameInnerInterceptor inner = new DynamicTableNameInnerInterceptor();
    inner.setTableNameHandler(new MyTableNameHandler());
    return inner;
}
public class MyTableNameHandler implements TableNameHandler {
    @Override
    public String dynamicTableName(String sql, String tableName) {
        Map
paramMap = RequestDataHelper.getRequestData();
        if (paramMap == null || paramMap.isEmpty()) {
            return tableName;
        }
        int random = (int) paramMap.get("tableNo");
        String suffix = (random % 2 == 1) ? "_2" : "_1";
        return tableName + suffix;
    }
}

6. Multi‑Tenant – reference to a previous article on SaaS multi‑tenant data isolation.

7. Summary – the tutorial covers practical advanced features of MyBatis‑Plus that improve development efficiency and reduce repetitive code.

JavaORMMyBatis-Plusbatch insertDynamic Tablelogical deleteType Handler
Java Tech Enthusiast
Written by

Java Tech Enthusiast

Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.