MyBatis-Plus primary key automatically generates source code analysis (problem: Primary key generation fails???)

MyBatis-Plus primary key automatically generates source code analysis (and problem primary key generation failure?)

reason:

When testing an added function today, an error was reported to me: (as follows)

### Error updating database.  Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'id' cannot be null

A very common problem, the id field of the database is the primary key is not null, it is empty when inserted. Constraint restrictions cause this exception to be thrown.

Ideas:

1. First check the annotations that should be added:

@TableName("数据库表名")
public class 类名 implements Serializable {
    
    

    private static final long serialVersionUID = 1L;

    /**
     * 自增记录
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    @JsonSerialize(using = ToStringSerializer.class)
    private Long id; //可以为 String 或者 Long

2. Then check whether the corresponding fields in the database match. ASSIGN_ID means that the number of digits generated by the snowflake algorithm is relatively large, and it needs to be stored in bigint . (There is no problem after checking)

3. Then check the yml configuration:

mybatis-plus:
  global-config:
    db-config:
      id-type: ASSIGN_UUID #也可以用3表示

No problem, because adding this configuration to the previous code has no effect, maybe the priority of the code is higher than the configuration (my guess.)

This is a headache, and it’s all right. Why is it empty? Later, I cleared the compiled file and recompiled, and then tried other primary key generation strategies, and there was no problem, except for ASSIGN_ID, which suddenly felt targeted. The series of operations are still useless. Baidu has no results (no similar problems).

So I had to track the source code to see what was going on.
1. Find the property and set a breakpoint, so I came to the MybatisDefaultParameterHandler class, which is used to handle the default parameter assignment.
There are many methods in it, but the method I need to find is this:

/**
     * 填充主键
     *
     * @param tableInfo  数据库表反射信息
     * @param metaObject 元数据对象
     * @param entity     实体信息
     */
    protected static void populateKeys(TableInfo tableInfo, MetaObject metaObject, Object entity) {
    
    
        final IdType idType = tableInfo.getIdType();
        final String keyProperty = tableInfo.getKeyProperty();
        if (StringUtils.isNotBlank(keyProperty) && null != idType && idType.getKey() >= 3) {
    
    
            final IdentifierGenerator identifierGenerator = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getIdentifierGenerator();
            Object idValue = metaObject.getValue(keyProperty);
            if (StringUtils.checkValNull(idValue)) {
    
    
                if (idType.getKey() == IdType.ASSIGN_ID.getKey()) {
    
    
                    if (Number.class.isAssignableFrom(tableInfo.getKeyType())) {
    
    
                        metaObject.setValue(keyProperty, identifierGenerator.nextId(entity)); //这个方法生成ID然后赋值
                    } else {
    
    
                        metaObject.setValue(keyProperty, identifierGenerator.nextId(entity).toString());
                    }
                } else if (idType.getKey() == IdType.ASSIGN_UUID.getKey()) {
    
    
                    metaObject.setValue(keyProperty, identifierGenerator.nextUUID(entity));
                }
            }
        }
    }

Look at the source code to know how to generate id:

identifierGenerator.nextId(entity)

So enter the method to view:

/**
 * Id生成器接口
 *
 * @author [email protected] nieqiuqiu
 * @since 2019-10-15
 * @since 3.3.0
 */
public interface IdentifierGenerator {
    
    

    /**
     * 生成Id
     *
     * @param entity 实体
     * @return id
     */
    Number nextId(Object entity);

    /**
     * 生成uuid
     *
     * @param entity 实体
     * @return uuid
     */
    default String nextUUID(Object entity) {
    
    
        return IdWorker.get32UUID();
    }

This is getting closer and closer to the truth (excited...)

Continue to look at the implementation class of nextId() .

@Slf4j
@Component
public class CustomIdGenerator implements IdentifierGenerator {
    
    

    @Override
    public Number nextId(Object entity) {
    
    
        return null;
    }

    /**
     * String 类型id生成
     *
     * @param entity
     * @return
     */
    @Override
    public String nextUUID(Object entity) {
    
    
        return IDGenerate.randomUUID();
    }
}

At this point, I am puzzled (B)???
What is the situation, the configuration class rewrites this method, and returns Null all the time. I don’t know who wrote the configuration class, it’s really a trap for me.

IdentifierGenerator identifierGenerator=new DefaultIdentifierGenerator();
        System.out.println(identifierGenerator.nextId(new Object()));  //单独使用雪花算法

That's all for today's article, I hope it can help you!

Guess you like

Origin blog.csdn.net/AKALXH/article/details/115524808