Причина события вот в чем.Требование-проверить данные по условиям и потом отобразить их на фронтенде.Когда писал его я думал что это очень просто.Разве не просто использовать динамический SQL MyBatis для запросить данные?
Реальность все еще очень жестока.После того, как я закончил писать UAT, студенты-передовики сказали, что согласноstate
Проверенные данные не соответствуют идеальным данным, этоstate
В то время было всего два значения по дизайну:0
и1
.
/**
* 数据状态
*/
@Range(min = 0, max = 1, message = "状态只能为0(未处理),1(已处理)")
private Integer state;
В идеале вы можете передать значение, переданное из внешнего интерфейса, а затем сделать sql-запрос:
<if test="req.state != null and req.state != ''">
AND md.state = #{req.state}
</if>
Вышеупомянутый sql сначала судитstate
не пустой ине пустая строка, затем добавьте сравнениеstate
поле. Взгляните первымif
С решением проблем нет, но я его вынесreq.state
даInteger
типа, смотри внимательноreq.state != null
Нет проблем, потом узналreq.state != ''
использоватьInteger
Сравните с пустой строкой.
Если интерфейс не передает его при запросеreq.state
Тотreq.state != null
Здесь он не будет удовлетворен, но передняя часть проходит0
когда ты придешьreq.state != ''
фактически вернулсяfalse
То есть в0 в MyBatis, если синтаксис равен пустой строке:
{
"state": 0
}
В этом сравнении нет ошибки, и оно немного сбивает с толку, нет другого пути, кроме как посмотреть исходный код MyBatis, чтобы выяснить причину.
Посмотреть исходный код MyBatis
Подробно процесс поиска других исходных кодов MyBatis описывать не будем, ищите прямо здесь.XMLScriptBuilder
класс, найтиif
Процесс разбора грамматики, а затем пошаговое исследование0 == ''
причина.XMLScriptBuilder
будет анализироватьtrim
,if
Для грамматики, поддерживаемой MyBatis, принцип синтаксического анализа заключается в следующем:NodeHandler
Чтобы анализировать разные теги по отдельности:
private void initNodeHandlerMap() {
nodeHandlerMap.put("trim", new TrimHandler());
nodeHandlerMap.put("where", new WhereHandler());
nodeHandlerMap.put("set", new SetHandler());
nodeHandlerMap.put("foreach", new ForEachHandler());
nodeHandlerMap.put("if", new IfHandler());
nodeHandlerMap.put("choose", new ChooseHandler());
nodeHandlerMap.put("when", new IfHandler());
nodeHandlerMap.put("otherwise", new OtherwiseHandler());
nodeHandlerMap.put("bind", new BindHandler());
}
Поскольку это неверно, синтаксисif
теги, просмотрIfHandler
Это нормально, просто игнорируйте остальное пока.
private class IfHandler implements NodeHandler {
public IfHandler() {
// Prevent Synthetic Access
}
@Override
public void handleNode(XNode nodeToHandle, List<SqlNode> targetContents) {
MixedSqlNode mixedSqlNode = parseDynamicTags(nodeToHandle);
String test = nodeToHandle.getStringAttribute("test");
IfSqlNode ifSqlNode = new IfSqlNode(mixedSqlNode, test);
targetContents.add(ifSqlNode);
}
}
MyBatis будетif
Этикетка абстрагируется вIfSqlNode
:
public class IfSqlNode implements SqlNode {
private final ExpressionEvaluator evaluator;
private final String test;
private final SqlNode contents;
public IfSqlNode(SqlNode contents, String test) {
this.test = test;
this.contents = contents;
this.evaluator = new ExpressionEvaluator();
}
@Override
public boolean apply(DynamicContext context) {
if (evaluator.evaluateBoolean(test, context.getBindings())) {
contents.apply(context);
return true;
}
return false;
}
}
Наконец немного бровь, MyBatis будетif
помеченtest
использование собственностиExpressionEvaluator
проверить,true
или дляfalse
:
public class ExpressionEvaluator {
public boolean evaluateBoolean(String expression, Object parameterObject) {
Object value = OgnlCache.getValue(expression, parameterObject);
if (value instanceof Boolean) {
return (Boolean) value;
}
if (value instanceof Number) {
return new BigDecimal(String.valueOf(value)).compareTo(BigDecimal.ZERO) != 0;
}
return value != null;
}
public Iterable<?> evaluateIterable(String expression, Object parameterObject) {
Object value = OgnlCache.getValue(expression, parameterObject);
if (value == null) {
throw new BuilderException("The expression '" + expression + "' evaluated to a null value.");
}
if (value instanceof Iterable) {
return (Iterable<?>) value;
}
if (value.getClass().isArray()) {
// the array may be primitive, so Arrays.asList() may throw
// a ClassCastException (issue 209). Do the work manually
// Curse primitives! :) (JGB)
int size = Array.getLength(value);
List<Object> answer = new ArrayList<Object>();
for (int i = 0; i < size; i++) {
Object o = Array.get(value, i);
answer.add(o);
}
return answer;
}
if (value instanceof Map) {
return ((Map) value).entrySet();
}
throw new BuilderException("Error evaluating expression '" + expression + "'. Return value (" + value + ") was not iterable.");
}
}
В итоге получил вывод:Используется МибатисомOgnl表达式
чтобы получить значение тестового свойства
последний аргумент
Уже известно, что MyBatis используется внутриOgnl表达式
,Да или нетOgnl表达式
вызвано этим? Вы узнаете это на практике, сначала введите зависимости:
<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>2.7.3</version>
</dependency>
Напишите тест программы:
public static void main(String[] args) {
Map<String, Object> objectMap = new HashMap<>();
objectMap.put("state", 0);
Object value = OgnlCache.getValue("state == ''", objectMap);
System.out.println(value);
}
Вывод вышеуказанной программы действительноtrue
. . .
Суммировать
Это спазм мозга.Integer
Также проверьте, является ли это пустой строкой. . .
Запишите эту яму, я надеюсь, что это поможет всем.
Добро пожаловать в официальный аккаунт: «Архитектурный дайджест». Получите эксклюзивные бесплатные учебные ресурсы 120G, которые помогут вашему архитектору учиться!
Фоновый ответ публичного аккаунта
arch028
Получить информацию: