跳至主要內容

状态计算属性

xuejmnet大约 3 分钟

比如您有一张证书表,证书表存在证书过期时间,那么证书有个动态的隐藏属性叫做状态,证书是否过期可以通过这个状态来实现

临期、过期、未过期



@Table("t_certificate")
@Data
@EntityProxy
public class Certificate implements ProxyEntityAvailable<Certificate , CertificateProxy> {
    @Column(primaryKey = true)
    private String id;
    /**
     * 证书名称
     */
    private String name;
    /**
     * 创建时间
     */
    private LocalDateTime createTime;
    /**
     * 过期时间
     */
    private String invalidTime;

    @Column(sqlConversion = CertStatusColumnValueSQLConverter.class)
    //因为不是真实列所以不需要插入
    @InsertIgnore
    //因为不是真实列所以不需要修改
    @UpdateIgnore
    private CertStatusEnum status;

}



@Getter
public enum CertStatusEnum implements IEnum<CertStatusEnum> {
    NORMAL(1,"正常"),

    WILL_INVALID(2,"临期"),

    INVALID(3,"过期");
    private final Integer code;
    private final String name;

    CertStatusEnum(Integer code,String name){

        this.code = code;
        this.name = name;
    }
    @Override
    public CertStatusEnum valueOf(Integer enumValue) {
        switch (enumValue){
            case 1:return NORMAL;
            case 2:return WILL_INVALID;
            case 3:return INVALID;
        }
        throw new UnsupportedOperationException();
    }
}





//证书状态值
@Component//非springboot自行注册比如solon
public class CertStatusColumnValueSQLConverter  implements ColumnValueSQLConverter {
    @Override
    public boolean isRealColumn() {
        //他不是一个真实存在的列所以返回false
        return false;
    }

    @Override
    public boolean isMergeSubQuery() {
        //期间没有用到别的数据库所以是false
        return false;
    }

    @Override
    public void selectColumnConvert(TableAvailable table, ColumnMetadata columnMetadata, SQLPropertyConverter sqlPropertyConverter, QueryRuntimeContext runtimeContext) {
        SQLFunc fx = runtimeContext.fx();
        //计算出两者天数差值 前面是大的时间后面是小的时间
        SQLFunction durationDay = fx.duration(x->x.column(table,"invalidTime").sqlFunc(fx.now()), DateTimeDurationEnum.Days);
        //计算出来的时间如果大于30天表示是正常的,大于等于0表示临期的小于0表示过期的
        SQLFunction sqlFunction = fx.anySQLFunction("(CASE WHEN {0}>30 THEN 1 WHEN {0}>=0 THEN 2 ELSE 3 END)", c -> {
            c.sqlFunc(durationDay);
        });
        String sqlSegment = sqlFunction.sqlSegment(table);
        sqlPropertyConverter.sqlNativeSegment(sqlSegment,context->{
            sqlFunction.consume(context.getSQLNativeChainExpressionContext());
            context.setAlias(columnMetadata.getName());//因为是返回所以需要设置别名
        });
    }

    @Override
    public void propertyColumnConvert(TableAvailable table, ColumnMetadata columnMetadata, SQLPropertyConverter sqlPropertyConverter, QueryRuntimeContext runtimeContext) {
        SQLFunc fx = runtimeContext.fx();
        SQLFunction durationDay = fx.duration(x->x.column(table,"invalidTime").sqlFunc(fx.now()), DateTimeDurationEnum.Days);
        SQLFunction sqlFunction = fx.anySQLFunction("(CASE WHEN {0}>30 THEN 1 WHEN {0}>=0 THEN 2 ELSE 3 END)", c -> {
            c.sqlFunc(durationDay);
        });
        String sqlSegment = sqlFunction.sqlSegment(table);
        sqlPropertyConverter.sqlNativeSegment(sqlSegment,context->{
            sqlFunction.consume(context.getSQLNativeChainExpressionContext());
            //当做属性用所以不需要别名
        });
    }

    @Override
    public void valueConvert(TableAvailable table, ColumnMetadata columnMetadata, SQLParameter sqlParameter, SQLPropertyConverter sqlPropertyConverter, QueryRuntimeContext runtimeContext, boolean isCompareValue) {
        //因为不做插入和修改所以这个status属性被用作条件比较的时候条件值还是原先的值
        sqlPropertyConverter.sqlNativeSegment("{0}",context->{
            context.value(sqlParameter);
        });
    }
}


//注册计算属性

QueryRuntimeContext runtimeContext = easyQuery.getRuntimeContext();
QueryConfiguration configuration = runtimeContext.getQueryConfiguration();
configuration.applyColumnValueSQLConverter(new CertStatusColumnValueSQLConverter());

查询

List<Certificate> list = easyEntityQuery.queryable(Certificate.class)
        .toList();

SELECT
    `id`,
    `name`,
    `create_time`,
    `invalid_time`,
    (CASE 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>30 THEN 1 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>=0 THEN 2 
        ELSE 3 
    END) AS `status` 
FROM
    `t_certificate` 

筛选


List<Certificate> list = easyEntityQuery.queryable(Certificate.class)
        .where(c -> c.status().eq(CertStatusEnum.NORMAL))
        .toList();


SELECT
    `id`,
    `name`,
    `create_time`,
    `invalid_time`,
    (CASE 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>30 THEN 1 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>=0 THEN 2 
        ELSE 3 
    END) AS `status` 
FROM
    `t_certificate` 
WHERE
    (
        CASE 
            WHEN timestampdiff(DAY, NOW(), `invalid_time`)>30 THEN 1 
            WHEN timestampdiff(DAY, NOW(), `invalid_time`)>=0 THEN 2 
            ELSE 3 
        END
    ) = 1

排序


List<Certificate> list = easyEntityQuery.queryable(Certificate.class)
        .where(c -> c.status().eq(CertStatusEnum.NORMAL))
        .orderBy(c -> c.status().asc())
        .toList();


--1条sql数据
SELECT
    `id`,
    `name`,
    `create_time`,
    `invalid_time`,
    (CASE 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>30 THEN 1 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>=0 THEN 2 
        ELSE 3 
    END) AS `status` 
FROM
    `t_certificate` 
WHERE
    (
        CASE 
            WHEN timestampdiff(DAY, NOW(), `invalid_time`)>30 THEN 1 
            WHEN timestampdiff(DAY, NOW(), `invalid_time`)>=0 THEN 2 
            ELSE 3 
        END
    ) = 1 
ORDER BY
    (CASE 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>30 THEN 1 
        WHEN timestampdiff(DAY,
        NOW(),
        `invalid_time`)>=0 THEN 2 
        ELSE 3 
    END) ASC
上次编辑于:
贡献者: Hoysing