imekaku's blog thinking reading about

JOOQ returning Null 解析


23 Jul 2018 - code

在使用jooq完成数据库更新的时候有类似这样的的操作:

UserRecord userRecord = dslContext.insertInto(USER)
        .set(USER.USERNAME, userinfoRequest.getUsername())
        .set(USER.CREATE_TIME, timestamp)
        .onDuplicateKeyIgnore()
        .returning()
        .fetchOne();

这里使用 onDuplicateKeyIgnore 如果有主键或者唯一索引,重复时不进行插入操作,并且返回插入的或者返回已经存在的记录,但是在这里是返回的Null。

debug发现在在 org.jooq.impl.AbstractDMLQuery有这样的逻辑:

case MYSQL:
    listener.executeStart(ctx);
    result = ctx.statement().executeUpdate();
    ctx.rows(result);
    listener.executeEnd(ctx);
    rs = ctx.statement().getGeneratedKeys();

    int var6;
    try {
        List<Object> list = new ArrayList();
        if (rs != null) {
            while(rs.next()) {
                list.add(rs.getObject(1));
            }
        }

        this.selectReturning(ctx.configuration(), list.toArray());
        var6 = result;
    } finally {
        JDBCUtils.safeClose(rs);
    }

    return var6;

这里如果数据库的自增键为空,那么直接执行 this.selectReturning() 函数。

private final void 
selectReturning(Configuration configuration, Object... values) {
    if (values != null && values.length > 0 
    	&& this.table.getIdentity() != null) {

        final Field<Object> field = this.table.getIdentity().getField();
        Object[] ids = new Object[values.length];

        for(int i = 0; i < values.length; ++i) {
            ids[i] = field.getDataType().convert(values[i]);
        }

        if (this.returning.size() == 1 
        	&& (new Fields(this.returning)).field(field) != null) {
            //...
        } else {
            this.returned = this.create(configuration)
            .select(this.returning)
            .from(this.table)
            .where(new Condition[]{field.in(ids)}).fetchInto(this.table);
        }
    }

}

第一个if语句是进不去的,this.table.getIdentity() == null 继续接下来的步骤。

public final Result<R> getReturnedRecords() {
    if (this.returned == null) {
        this.returned = 
        new ResultImpl(this.configuration(), this.returning);
    }

    return this.returned;
}
///...
public final R fetchOne() {
    ((InsertQuery)this.getDelegate()).execute();
    return Tools.filterOne(((InsertQuery)this.getDelegate())
    	.getReturnedRecords());
}

static final <R extends Record> 
R filterOne(List<R> list) throws TooManyRowsException {
    int size = list.size();
    if (size == 1) {
        return (Record)list.get(0);
    } else if (size > 1) {
        throw new TooManyRowsException("Too many rows selected : " + size);
    } else {
        return null;
    }
}

所以当数据库的没有自增键的时候,返回的结果是Null。