使用mybatis plus生成 id主键时会遇到哪些问题
更新时间:2023-10-10什么情况下会遇到mybatis plus生成id主键产生问题
使用MyBatis-Plus(简称MP)是我们近年来开发中的一项必备技术,它减少了我们对繁琐SQL的编写,提高了我们的开发效率。但是在使用MP时,我们很容易因为一些配置问题导致主键生成不了甚至存在主键冲突的问题,特别是在分布式架构的环境下更为明显。
主键生成策略引起的问题
MP中默认提供了几种主键生成策略,例如:UUID,自增,雪花算法等。这里以MP默认提供的雪花算法为例。如果我们在生产环境下使用了MP自带的雪花算法,则会存在一些潜在的问题:
- 主键生成依赖于时间戳,存在时间差会产生冲突
- 如果进程间时钟不同步,会导致分布式环境下主键重复问题
当然我们可以手动实现主键生成策略,这样可以避免上述问题,示例代码如下:
public class CustomIdGenerator implements IdentifierGenerator { @Override public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException { // TODO 根据实际需求生成主键 return null; } }
主键生成设置不当引起的问题
除了主键生成策略问题外,我们还有可能会因为设置不当而导致主键生成不正确。下面举例说明。
- 一般情况下,我们使用JPA Entity注解来设置主键(如下面代码所示)。然而在实际开发中,我们会发现主键没有生成,这是因为我们需要在实体类中加上@TableId注解:
@Entity public class User { @Id private Long id; // 这里未加@TableId注解 private String name; }
@Entity public class User { @TableId(type = IdType.AUTO) private Long id; // 加上@TableId注解 private String name; }
另外,我们需要注意的是:在实体类中设置主键生成策略的优先级最高,如果我们在实体类中设置了主键生成策略,而在MP的全局配置中也设置了一套不同的主键生成策略,实际使用的是实体类中的主键生成,如下示例所示:
@Entity public class User { @TableId(type = IdType.AUTO) // 使用了雪花算法 private Long id; private String name; }
// 这里定义了全局主键生成策略 @Configuration public class MybatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); Properties properties = new Properties(); properties.setProperty("autoWorkerIdRetryTimes", "10"); SnowflakeKeyGenerator keyGenerator = new SnowflakeKeyGenerator(); keyGenerator.setProperties(properties); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); interceptor.addInnerInterceptor(new IllegalSQLInnerInterceptor()); interceptor.addInnerInterceptor(keyGenerator); // 使用了UUID return interceptor; } }
总结
在使用MyBatis-Plus生成ID主键时,需要注意以下几点:
- 正确配置主键生成策略,避免主键冲突
- 正确在实体类中设置@TableId注解,避免主键未生成
- 全局主键生成策略不能覆盖实体类中的主键生成策略,避免出现无法预料的问题