回顾
上次我们重写了QueryWrapper,解决了无法得到QueryWrapper中字段名称的问题,但是问题并没有这么简单,咱们再次接下来的兼容性改造。
问题
实际研发中大家怎么用的都有,其中QueryWrapper的And语法就直接报错了.如下图:
java.lang.NullPointerException: null
at cn.bjca.logServer.client.QueryWrapper.getSqlSelect(QueryWrapper.java:61) ~[classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_221]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_221]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_221]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_221]
at org.apache.ibatis.ognl.OgnlRuntime.invokeMethodInsideSandbox(OgnlRuntime.java:1269) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1254) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.OgnlRuntime.getMethodValue(OgnlRuntime.java:2160) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.ObjectPropertyAccessor.getPossibleProperty(ObjectPropertyAccessor.java:66) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.ObjectPropertyAccessor.getProperty(ObjectPropertyAccessor.java:160) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.OgnlRuntime.getProperty(OgnlRuntime.java:3338) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.ASTProperty.getValueBody(ASTProperty.java:121) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.ASTChain.getValueBody(ASTChain.java:141) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212) ~[mybatis-3.5.6.jar:3.5.6]
at org.apache.ibatis.ognl.SimpleNode.getValue(SimpleNode.java:258) ~[mybatis-3.5.6.jar:3.5.6]
使用api如下:
cn.bjca.logServer.client.QueryWrapper<Notice> noticeQueryWrapper = new cn.bjca.logServer.client.QueryWrapper<>();
if (StrUtil.isEmpty(enterpriseId)) {
noticeQueryWrapper.and(noticeQueryWrapper1 -> noticeQueryWrapper1.eq("user_id", userId)
.eq("enterprise_id", CommonConstant.INT_ONE));
} else {
noticeQueryWrapper.and(noticeQueryWrapper1 -> noticeQueryWrapper1.eq("user_id", userId)
.eq("enterprise_id", enterpriseId));
noticeQueryWrapper.or(noticeQueryWrapper1 -> noticeQueryWrapper1
.eq("user_id", CommonConstant.INT_ONE).eq("enterprise_id", enterpriseId));
}
原因查找
发现是在getSelect的时候报空了,打开源码发现它的构造有如下:
正是在构造方法中实例化的sqlSelect。
解决方案
我们也编写构造方法,并且在构造方法中调用父构造器代码如下:
public class QueryWrapper<T> extends com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T> implements Wrapper {
private static final String MP_GENERAL_PARAMNAME = "MPGENVAL";
private final SharedString sqlSelect;
public QueryWrapper() {
super();
this.sqlSelect = new SharedString();
}
public QueryWrapper(T entity, String... columns) {
super(entity, columns);
this.sqlSelect = new SharedString();
}
private QueryWrapper(T entity, Class<T> entityClass, AtomicInteger paramNameSeq, Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments) {
super(entity);
this.sqlSelect = new SharedString();
this.entityClass = entityClass;
this.paramNameSeq = paramNameSeq;
this.paramNameValuePairs = paramNameValuePairs;
this.expression = mergeSegments;
}
public LambdaQueryWrapper<T> lambda() {
return new LambdaQueryWrapper(this.entity, this.entityClass, this.sqlSelect, this.paramNameSeq, this.paramNameValuePairs, this.expression);
}
@Override
protected com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<T> addCondition(boolean condition, String column, SqlKeyword sqlKeyword, Object val) {
columnMetaData.add(column);
return super.addCondition(condition, column, sqlKeyword, val);
}
@Override
public Object getParamNameValuePairsByKey(int name) {
return super.getParamNameValuePairs().get(MP_GENERAL_PARAMNAME+name);
}
@Override
public void setParamNameValuePairs(int name, Object value) {
super.getParamNameValuePairs().put(MP_GENERAL_PARAMNAME+name,value);
}
protected QueryWrapper<T> instance() {
return new QueryWrapper(this.entity, this.entityClass, this.paramNameSeq, this.paramNameValuePairs, new MergeSegments());
}
}
涉及到的4个Wrapper类全部添加对应的构造至此基本兼容Wrapper类的所有语法(当然还有未知的可能性)。