slyak / spring-data-jpa-extra

spring data jpa with template dynamic query (eg: freemarker,velocity etc.) like mybatis. The master branch already support springboot2+ spring5+
Apache License 2.0
400 stars 116 forks source link

关于单元测试代码和README.md代码中无法传参的坑 #22

Closed lieberliang closed 6 years ago

lieberliang commented 6 years ago

首先说明这并不是您代码的问题,应该是您的未描述清楚,导致初使用者走了弯路。我按照您的说明以及单元测试中的代码去尝试使用时发现,不论我怎么改SampleRepository.findByContent方法中参数以及*.sftl文件,最终打印出来的查询语句中<#if></#if>中的内容是一直没有的,问题原因如下:

FreemarkerTemplateQuery.getParams()的返回值中Map的内容一直为null --> value,那么导致freemarker格式化的时候一直忽略掉了<#if></#if>中的内容。解决方法必须加上@Param注解,即

    @TemplateQuery
    Page<Sample> findByContent(@Param("content") String content, Pageable pageable);

具体原因如下: FreemarkerTemplateQuery.getParams()MapKey看您是通过Parameter.getName()获得,其源码如下:

    public String getName() {
        Param annotation = parameter.getParameterAnnotation(Param.class);
        return annotation == null ? parameter.getParameterName() : annotation.value();
    }

以上代码中parameterMethodParameter对象,其方法getParameterName()具体如下:

    public String getParameterName() {
        ParameterNameDiscoverer discoverer = this.parameterNameDiscoverer;
        if (discoverer != null) {
            String[] parameterNames = (this.method != null ?
                    discoverer.getParameterNames(this.method) : discoverer.getParameterNames(this.constructor));
            if (parameterNames != null) {
                this.parameterName = parameterNames[this.parameterIndex];
            }
            this.parameterNameDiscoverer = null;
        }
        return this.parameterName;
    }

返回值依赖于ParameterNameDiscoverer对象,并且如果首次取不到则会将this.parameterNameDiscoverer置空,下次取仍返回空,在org.springframework.data.repository.query.Parameters中查看MethodParameter.parameterNameDiscoverer使用的是DefaultParameterNameDiscoverer对象,其最终依赖于jdk8中Parameter反射对象获得,如果未通过–parameters参数指明编译时不会保留语义,则Parameter.getName()中的parameter.getParameterName()一直都是返回空的。那么只能依赖于@Param

或许因为我是首次使用mybatis以及spring data jpa原因有些特性可能我并不清楚,只能依赖于测试用例及README中的说明,另外,*.sftl的文件名必须要与Entity名对应这个您可能也要说明一下,不调源码真不知道有这限制。

stormning commented 6 years ago

分析得很透彻👍。这个spring-data-jpa本身也是按照这个逻辑获取param的,而我这个是基于它的扩展,然后我就默认大家都知道这个潜规则了,所以未做描述。 谢谢提醒,ReadMe的坑我先填上

stormning commented 6 years ago

README说明已加,后面我会整理较为一个完整的说明文档,非常感谢,我先把这个关闭了 https://github.com/slyak/spring-data-jpa-extra/issues/3

ssy341 commented 6 years ago

@stormning 非常方便的工具,很受益,感谢 @lieberliang 感谢解释的那么清楚,我也掉进了这个坑 readme和test代码不一致,直接用的test代码,根本没注意readme,期待更详细的文档

ssy341 commented 6 years ago

@lieberliang 请教一个问题,findMap这个测试方法我使用2.1.2版本,会抛出null指针,你有遇到这个问题么?我提了issue #31