Solr7.2.1 @Field标签类型转换错误

在项目中使用到Bigdecimal类型表示金钱,但是Solr中并没有Bigdecimal这种类型,所以我的情况就是

数据库basePrice 字段设置为decimal类型

Solr中basePrice配置 为string类型

POJO中设置为Bigdecimal类型

然后想直接使用Solr提供的@Field标签完成字段的自动映射,但是在测试的时候报错:

Caused by: org.apache.solr.client.solrj.beans.BindingException: Exception while setting value : 522.0 on public java.math.BigDecimal cn.wolfcode.shop.server.P.basePrice

查看错误源码发现底层是使用反射依次设值的,但是java中的Bigdecimal类型在反射时如果使用常用的field.set(obj,val)

会报错,也就是说这个错误实际上是因为Bigdecimal类型的字段的反射调用跟其他的有些不同,而solr并没有对其进行特殊处理,如果你使用了@Field标签对Bigdecimal类型进行映射那就会报错

解决方法也很简单,你可以修改源码加判断,我是自己写了一个方法进行处理,不用solr提供的getBeans方法

public <T> List<T> queryBean(SolrParams params, Class<T> clazz) throws Exception {
    QueryResponse response = client.query(coreName, params);
    response.getResults().getNumFound();
    SolrDocumentList documents = response.getResults();
    List<T> list = new ArrayList<T>();
    T obj = null;
    for (SolrDocument solrDocument : documents) {
        //反射出实例
        obj = clazz.newInstance();
        //获取所有属性
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //判断这个属性上是否存在注解SolrField //存在的话 设置值
            if (field.isAnnotationPresent(org.apache.solr.client.solrj.beans.Field.class)) {
                //获取注解
                org.apache.solr.client.solrj.beans.Field solrField = field.getAnnotation(org.apache.solr.client.solrj.beans.Field.class);
                field.setAccessible(true);
                if ("#default".equals(solrField.value()) || "".equals(solrField.value())) {
                    // 如果注解为默认的 采用此属性的name来从solr中获取值
                    if (field.getType() == BigDecimal.class) {
                        field.set(obj, new BigDecimal(solrDocument.get(field.getName()).toString()));
                    } else {
                        field.set(obj, solrDocument.get(field.getName()));
                    }
                } else {
                    // 如果注解为不是默认的 采用此注解上的值来从solr中获取值
                    field.set(obj, solrDocument.get(solrField.value()));
                }
            }
        }
        list.add(obj);
    }
    return list;

}
但是如果业务不多的话建议还是直接手动使用setter方法进行封装吧,毕竟反射的性能还是挺低的


你可能感兴趣的:(Solr,java)