• 接口返回null值原来是我的SQL语句写错了
  • 发布于 2个月前
  • 237 热度
    0 评论
 在实际场景中提供了N个接口给第三方,常规情况下是不会同时调用的,如果N个接口同时调用,随着接口的数量和业务场景逻辑增加,将会给服务带来很不好的体验,但恰恰业务就是如此,面对同一类型的业务查询场景,我将策略模式应用到此接口上来应对。

这个对外接口与以往不同的是,接口调用通过openFeign方式调用,针对此类调用也提醒了注意事项CompletableFuture调用OpenFegin,谁用谁傻,除了业务需求的更改,已经是上线逻辑了,但偶发的出现了返回数据为null的情况,针对业务已经对Integer做了处理,正常的应该是返回0的,且出现null的情况也未能复现,针对代码做出排查。

ApplicationContext可以同时获取多个Bean吗?
其实这个问题不应该这么问,多线程调用的默认Springboot的无状态Bean是线程安全的,一般情况下是不会对Bean的成员变量进行修改的,这个跟修改注解的方法值那个问题是两个问题,context无非是一个map,当在外部进行调用的前提,我所需要的我bean是一定已经初始化完成的,我们看下context的内部存储数据:

在这里可以看到已经初始化的bean,或者在beanDefinitionMap中也能看到,只不过在其实现中是有区别的,比如在SimpleJndiBeanFactory中其getBean方法是一个HashMap,而在DefaultListableBeanFactory中则是ConcurrentHashMap,所以不管是哪种类型,在map中同时获取bean是没有问题的,即便是在多线程场景下。考虑到版本和镜像初始化问题,如果需要可以在bean初始化完成之后进行指定bean的初始化。

1.实现ApplicationListener接口
Bean在初始化完成后会执行onApplicationEvent方法
// 堆代码 duidaima.com
@Component
public class LazyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    public LazyApplicationListener() {
        System.out.println("LazyApplicationListener init");
    }

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        if (event.getApplicationContext().getParent() == null) {
            System.out.println("LazyApplicationListener onApplicationEvent");
        }
    }
}
2.实现InitializingBean接口
Bean在初始化完成后会执行afterPropertiesSet()
@Component
public class LazyInitializingBean implements InitializingBean {
    public LazyInitializingBean() {
        System.out.println("LazyInitializingBean init");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("LazyInitializingBean afterPropertiesSet");
    }
}
3.使用@PostConstruct注解
@Component
public class LazyPostConstructAnnotation {
    public LazyPostConstructAnnotation() {
        System.out.println("LazyPostConstructAnnotation constructor");
    }

    @PostConstruct
    public void init(){
        System.out.println("LazyPostConstructAnnotation init");
    }
}
2023-01-09 17:29:55.588  INFO 5884 --- [main] o.s.web.context.ContextLoader            : 
Root WebApplicationContext: initialization completed in 2489 ms

那么为何为null?
SQL语句不能保证100%为null,原sql如下
 <select id="task" resultType="java.lang.Integer">
        select  count(*)  from  (select  id from xxx tri
                                 where xxx
                                   xxx
                                   xxx
                                 GROUP BY xxx) a
   </select>
count(字段名):返回select语句检索的行中字段名的值不为null的数量,结果是BIGINT值;
count(*):统计结果中会包含值为null的行数;
count(常量):count(*)、count(常量):表示的是直接查询符合条件的数据库表的行数。而count(列名)表示的是查询符合条件的列的值不为null的行数;

原因猜测   
如果确实为null可手动处理Integer值。但其实并没有再次复现此问题,我其实怀疑是因为在这个期间我某个SQL当时写错了,构建完没改的情况导致在一个接口同时调用时报错,从而返回了null。
用户评论