繁体   English   中英

如何强制 Mybatis 使用动态条件进行区分大小写的选择

[英]How to force Mybatis to do a case sensitive select using dynamic criteria

我正在为 Mybatis DB 映射器构建动态查询,以访问 MySql 数据库。 查询由包含选择字段的 XML 配置文件驱动。 所以我动态创建了一个 critera 对象。 我的问题是,如果选择字段之一是字符串,则选择返回不需要的记录,因为它不区分大小写

例如,如果选择值为“Analog1”,这将匹配值为“analog1”的记录。

问题是,我可以强制底层 SELECT 区分大小写吗? 我知道

select * from Label where binary Label_Name = 'analog1';

只会匹配 'analog1' 而不是 'Analog1'。 但是如何告诉 Mybatis 查询在查询中使用二进制限定符呢?

这是我创建条件的代码。 如您所见,这一切都是使用反射动态完成的,没有任何硬编码:

private Object findMatchingRecord(TLVMessageHandlerData data, Object databaseMapperObject, Object domainObject, ActiveRecordDataType activeRecordData)
        throws TLVMessageHandlerException {

    if (activeRecordData == null) {
        return false;
    }

    String domainClassName = domainObject.getClass().getName();

    try {
        String exampleClassName = domainClassName + "Example";
        Class<?> exampleClass = Class.forName(exampleClassName);
        Object exampleObject = exampleClass.newInstance();
        Method createCriteriaMethod = exampleClass.getDeclaredMethod("createCriteria", (Class<?>[])null);
        Object criteriaObject = createCriteriaMethod.invoke(exampleObject, (Object[])null);

        for (String selectField : activeRecordData.getSelectField()) {
            String criteriaMethodName = "and" + firstCharToUpper(selectField) + "EqualTo";
            Class<?> selectFieldType = domainObject.getClass().getDeclaredField(selectField).getType();
            Method criteriaMethod = criteriaObject.getClass().getMethod(criteriaMethodName, selectFieldType);
            Method getSelectFieldMethod = domainObject.getClass().getDeclaredMethod("get" + firstCharToUpper(selectField));
            Object selectFieldValue = getSelectFieldMethod.invoke(domainObject, (Object[])null);
            if (selectFieldValue != null) {
                criteriaMethod.invoke(criteriaObject, new Object[] { selectFieldValue });
            }
        }

        List<?> resultSet = tlvMessageProcessingDelegate.selectByExample(databaseMapperObject, exampleObject);

        if (resultSet.size() > 0) {
            return resultSet.get(0);
        }
        else {
            return null;
        }

    } 
    catch(..... Various exceptions.....) {
    }

有一种方法可以通过修改用于创建查询条件的“示例”类来做到这一点。 假设您有一个名为Label的 Mybatis 域对象。 这将有一个关联的LabelExample 请注意,我已将“二进制”限定符添加到生成的标准方法中。 这似乎为我完成了这项工作,并导致区分大小写的查询。

public class LabelExample {

...

/**
 * This class was generated by MyBatis Generator. This class corresponds to the database table Label
 * @mbggenerated
 */
    protected abstract static class GeneratedCriteria {

        public Criteria andLabelNameEqualTo(String value) {
            addCriterion("binary Label_Name =", value, "labelName");
            return (Criteria) this;
        }
    ...
}

我相信这是可能的,但不能使用简单的查询样式。

这在Mybatis Generator 文档中定义为以下形式:

TestTableExample example = new TestTableExample();
example.createCriteria().andField1EqualTo("abc");

这会导致这样的查询过滤器:

where field1 = 'abc'

相反,我认为您需要使用复杂的查询表单并将其与插件结合以启用ILIKE -esque 搜索。

有一个这样的插件示例,它随mybatis-generator 一起提供 为了完整起见,我重现了下面的代码:

/*
 *  Copyright 2009 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.mybatis.generator.plugins;

import java.util.List;

import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.IntrospectedColumn;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.InnerClass;
import org.mybatis.generator.api.dom.java.JavaVisibility;
import org.mybatis.generator.api.dom.java.Method;
import org.mybatis.generator.api.dom.java.Parameter;
import org.mybatis.generator.api.dom.java.TopLevelClass;
import org.mybatis.generator.codegen.ibatis2.Ibatis2FormattingUtilities;

/**
 * This plugin demonstrates adding methods to the example class to enable
 * case-insensitive LIKE searches. It shows hows to construct new methods and
 * add them to an existing class.
 * 
 * This plugin only adds methods for String fields mapped to a JDBC character
 * type (CHAR, VARCHAR, etc.)
 * 
 * @author Jeff Butler
 * 
 */
public class CaseInsensitiveLikePlugin extends PluginAdapter {

    /**
     * 
     */
    public CaseInsensitiveLikePlugin() {
        super();
    }

    public boolean validate(List<String> warnings) {
        return true;
    }

    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,
            IntrospectedTable introspectedTable) {

        InnerClass criteria = null;
        // first, find the Criteria inner class
        for (InnerClass innerClass : topLevelClass.getInnerClasses()) {
            if ("GeneratedCriteria".equals(innerClass.getType().getShortName())) { //$NON-NLS-1$
                criteria = innerClass;
                break;
            }
        }

        if (criteria == null) {
            // can't find the inner class for some reason, bail out.
            return true;
        }

        for (IntrospectedColumn introspectedColumn : introspectedTable
                .getNonBLOBColumns()) {
            if (!introspectedColumn.isJdbcCharacterColumn()
                    || !introspectedColumn.isStringColumn()) {
                continue;
            }

            Method method = new Method();
            method.setVisibility(JavaVisibility.PUBLIC);
            method.addParameter(new Parameter(introspectedColumn
                    .getFullyQualifiedJavaType(), "value")); //$NON-NLS-1$

            StringBuilder sb = new StringBuilder();
            sb.append(introspectedColumn.getJavaProperty());
            sb.setCharAt(0, Character.toUpperCase(sb.charAt(0)));
            sb.insert(0, "and"); //$NON-NLS-1$
            sb.append("LikeInsensitive"); //$NON-NLS-1$
            method.setName(sb.toString());
            method.setReturnType(FullyQualifiedJavaType.getCriteriaInstance());

            sb.setLength(0);
            sb.append("addCriterion(\"upper("); //$NON-NLS-1$
            sb.append(Ibatis2FormattingUtilities
                    .getAliasedActualColumnName(introspectedColumn));
            sb.append(") like\", value.toUpperCase(), \""); //$NON-NLS-1$
            sb.append(introspectedColumn.getJavaProperty());
            sb.append("\");"); //$NON-NLS-1$
            method.addBodyLine(sb.toString());
            method.addBodyLine("return (Criteria) this;"); //$NON-NLS-1$

            criteria.addMethod(method);
        }

        return true;
    }
}

实现起来似乎有点痛苦,不幸的是,高级Mybatis功能似乎经常出现这种情况,唯一的文档实际上是检入git repo 的示例。

您可能想看看使用内置于MybatisSQL Builder类,您可以在其中使用WHERE方法并在参数中指定ILIKE ,尽管我知道考虑到生成器代码的当前使用情况,这可能是一个桥梁。

有一个 mybatis 生成器插件org.mybatis.generator.plugins.CaseInsensitiveLikePlugin

该插件向 Example 类(实际上是 Criteria 内部类)添加方法以支持不区分大小写的 LIKE 搜索

您可以使用不敏感的“XXXX”,它可以与任何数据库一起使用

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM