当前使用版本(必填,否则不予处理)
<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);
}
}