mybatis-mapper / mapper

MyBatis Mapper
https://mapper.mybatis.io
Apache License 2.0
325 stars 47 forks source link

现在的 ExampleWrapper 提供的一系列 带 useCondition 的方法有个小弊端 #46

Closed ydq closed 1 year ago

ydq commented 1 year ago

RT:现在的 ExampleWrapper 提供的一系列 带 useCondition 的方法有个小弊端,期望可以改进一下

先来一段code:

//有空指针风险的 不推荐用法
someMapper.wrapper()
        .eq( 
            dto != null && StringUtils.isNotEmpty(dto.getField()) ,  //condition 为 true 下面的操作才生效
            Entity::getField , 
            dto.getField()   // 如果 dto 可能为空的话  此处是有空指针风险的
        )
        //....

这是当前的 ExampleWrapper 提供的带 condition 的方法,原本是 如果参数不为空,则执行后面的操作 但是这个地方有个问题,当 dto 为空的时候,因为后面的条件直接是立刻求值计算好了将返回值作为参数 所以可能导致最后的 dto.getField() 出现空指针

现在的临时的解决方案

//当前避免空指针操作的方法
someMapper.wrapper()
        .eq( 
            dto != null && StringUtils.isNotEmpty(dto.getField()) ,  // condition 为 true 下面的操作才生效
            Entity::getField , 
            Optional.ofNullable(dto).map(Dto::getField).orElse(null))  //为了防止空指针,只能再判断一次
        )
        //....

如果改成一个 Supplier,使其取值操作变成一个惰性的,而在exampleWrapper中做了condition的判断,那这样就不会产生空指针的异常了,即安全的操作应该是:

//期望直接支持接收 Supplier 作为条件
someMapper.wrapper()
        .eq( 
            dto != null && StringUtils.isNotEmpty(dto.getField()) ,  // condition 为 true 下面的操作才生效
            Entity::getField , 
            () ->  dto.getField()  //使用 Supplier 延迟获取, condition 为 false 的时候不执行,这样就不会空指针也少一次判断
        )
        //....

@abel533 如果接受建议的话,我可以提个PR

abel533 commented 1 year ago

接受建议,PR吧。

注意不要修改已有方法,可以增加新的 Supplier 的方法(如eq(boolean,Fn,Supplier))。