当前使用版本(必填,否则不予处理)

   <java.version>1.8</java.version>
    <mybatis-plus-generator.version>3.1.2</mybatis-plus-generator.version>
    <mybatis-plus.version>3.1.2</mybatis-plus.version>
    <mybatis-plus-extension.version>3.1.2</mybatis-plus-extension.version>
    <mybatis-plus-boot-starter.version>3.1.2</mybatis-plus-boot-starter.version>
    <mybatis-ehcache.version>1.0.0</mybatis-ehcache.version>
    <druid-spring-boot-starter.version>1.1.18</druid-spring-boot-starter.version>

重要提示

不考虑直接修改mybatis-plus版本来解决这个问题(比如直接升级到最新版本),因为我现在做的很多应用都是基于这个版本来做的,一旦修改工作量就变得很大,如果实在没办法看下是否考虑和美团的主键生成整合。

该问题是如何引起的?(确定最新版也有问题再提!!!)

使用下方的代码插入连续的数据会导致主键重复问题 第一次访问 127.0.0.1:1000/area/save 数据插入正常 接着第二次访问 127.0.0.1:1000/area/save 出现主键重复异常

@RestController
@RequestMapping("/area")
public class AreaController {

    @Autowired
    private IAreaService areaService;

    /**
     * 模拟插入数据
     */
    List<Area> list = Lists.newArrayList();

    @PostConstruct
    private void getData() {
        list.add(new Area("110000", "北京市"));
        list.add(new Area("110101", "东城区"));
        list.add(new Area("110102", "西城区"));
        list.add(new Area("110106", "丰台区"));
    }

    @PostMapping("/save")
    public ResponseData<?> save() {
        areaService.saveBatch(list);
        return ResponseData.out(CodeEnum.SUCCESS, null);
    }

}

实体类

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Area extends Model<Area> {

    private static final long serialVersionUID = 1L;

    /**
     * id
     */
    @TableId(value = "id", type = IdType.ID_WORKER)
    private Long id;

    /**
     * 地区编号
     */
    private String areaCode;

    /**
     * 地区名称
     */
    private String areaName;

    /**
     * 创建时间
     */
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    private LocalDateTime updateTime;

    @Override
    protected Serializable pkVal() {
        return this.id;
    }

    public Area(String areaCode, String areaName) {
        this.areaCode = areaCode;
        this.areaName = areaName;
    }
}

表格信息

CREATE TABLE `test`.`Untitled`  (
  `id` bigint(20) UNSIGNED NOT NULL COMMENT 'id',
  `area_code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '地区编号',
  `area_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '地区名称',
  `create_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '地区表(单库单表)' ROW_FORMAT = Dynamic;

完整代码地址

https://gitee.com/my51/mybatis-plus-id.git

sql文件在sql文件夹下

报错信息

Caused by: java.sql.BatchUpdateException: Duplicate entry '1260869145038475265' for key 'PRIMARY'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.cj.util.Util.handleNewInstance(Util.java:192)
    at com.mysql.cj.util.Util.getInstance(Util.java:167)
    at com.mysql.cj.util.Util.getInstance(Util.java:174)
    at com.mysql.cj.jdbc.exceptions.SQLError.createBatchUpdateException(SQLError.java:224)
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchSerially(ClientPreparedStatement.java:853)
    at com.mysql.cj.jdbc.ClientPreparedStatement.executeBatchInternal(ClientPreparedStatement.java:435)
    at com.mysql.cj.jdbc.StatementImpl.executeBatch(StatementImpl.java:796)
    at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3066)
    at com.alibaba.druid.filter.FilterAdapter.statement_executeBatch(FilterAdapter.java:2497)
    at com.alibaba.druid.filter.FilterEventAdapter.statement_executeBatch(FilterEventAdapter.java:279)
    at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3064)
    at com.alibaba.druid.wall.WallFilter.statement_executeBatch(WallFilter.java:510)
    at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3064)
    at com.alibaba.druid.filter.FilterAdapter.statement_executeBatch(FilterAdapter.java:2497)
    at com.alibaba.druid.filter.FilterEventAdapter.statement_executeBatch(FilterEventAdapter.java:279)
    at com.alibaba.druid.filter.FilterChainImpl.statement_executeBatch(FilterChainImpl.java:3064)
    at com.alibaba.druid.proxy.jdbc.StatementProxyImpl.executeBatch(StatementProxyImpl.java:202)
    at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeBatch(DruidPooledPreparedStatement.java:565)
    at com.baomidou.mybatisplus.core.executor.MybatisBatchExecutor.doFlushStatements(MybatisBatchExecutor.java:132)
    ... 73 common frames omitted

Comment From: miemieYaho

同一个对象insert后id会有值,再次插入id有值则不会再赋值了

Comment From: flypangzhi

同一个对象insert后id会有值,再次插入id有值则不会再赋值了

按照你的提示重新调整代码,发现是自己的测试代码写错了

(1)@PostConstruct注解是在应用启动的时候执行,而不是非要在post请求前执行 (2)@PostConstruct注解的内容只会执行一次 (3)controller默认是单例的,在里面直接定义属性很容易引发线程安全问题

这是我修改后的代码,多次测试可以正常运行生成的ID是趋势自增,非常感谢哈

@RestController
@RequestMapping("/area")
public class AreaController {

    @Autowired
    private IAreaService areaService;

    @PostMapping("/save")
    public ResponseData<?> save() {
        List<Area> list = new ArrayList<>();
        list.add(new Area("110000", "北京市"));
        list.add(new Area("110101", "东城区"));
        list.add(new Area("110102", "西城区"));
        list.add(new Area("110106", "丰台区"));
        areaService.saveBatch(list);
        return ResponseData.out(CodeEnum.SUCCESS, null);
    }

    @GetMapping("/list")
    public ResponseData<?> list() {
        List<Area> aList = areaService.list();
        return ResponseData.out(CodeEnum.SUCCESS, aList);
    }
}