简体   繁体   English

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

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

I'm constructing a dynamic query for a Mybatis DB mapper, to access a MySql database.我正在为 Mybatis DB 映射器构建动态查询,以访问 MySql 数据库。 The query is driven by an XML config file containing select fields.查询由包含选择字段的 XML 配置文件驱动。 So I dynamically create a critera object.所以我动态创建了一个 critera 对象。 My problem is, if one of the select fields is a string, the select returns unwanted records due to it being case insensitive我的问题是,如果选择字段之一是字符串,则选择返回不需要的记录,因为它不区分大小写

For example, if the select value is 'Analog1', this will match a record with value 'analog1'.例如,如果选择值为“Analog1”,这将匹配值为“analog1”的记录。

Question is, can I force the underlying SELECT to be case sensitive?问题是,我可以强制底层 SELECT 区分大小写吗? I know that我知道

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

Will only match 'analog1' and not 'Analog1'.只会匹配 'analog1' 而不是 'Analog1'。 But how to tell the Mybatis query to use the binary qualifier in the query?但是如何告诉 Mybatis 查询在查询中使用二进制限定符呢?

Here's my code to create the criteria.这是我创建条件的代码。 As you can see it's all dynamically done using reflection, there's nothing hardcoded:如您所见,这一切都是使用反射动态完成的,没有任何硬编码:

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.....) {
    }

There's a way to do this by modifying the 'Example' class used to create query criteria.有一种方法可以通过修改用于创建查询条件的“示例”类来做到这一点。 Suppose you have a Mybatis domain object called Label .假设您有一个名为Label的 Mybatis 域对象。 This will have an associated LabelExample .这将有一个关联的LabelExample Notice I've added the 'binary' qualifier to the generated criteria method.请注意,我已将“二进制”限定符添加到生成的标准方法中。 This appears to do the job for me, and results in a case sensitive query.这似乎为我完成了这项工作,并导致区分大小写的查询。

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;
        }
    ...
}

I believe it's possible to do, but not using the simple queries style.我相信这是可能的,但不能使用简单的查询样式。

That's defined in the Mybatis Generator doc as this form:这在Mybatis Generator 文档中定义为以下形式:

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

Which results in a query filter like this:这会导致这样的查询过滤器:

where field1 = 'abc'

Instead, I think you need to use the complex queries form and combine it with a plugin to enable ILIKE -esque searches.相反,我认为您需要使用复杂的查询表单并将其与插件结合以启用ILIKE -esque 搜索。

There is an example of such a plugin that ships with mybatis-generator .有一个这样的插件示例,它随mybatis-generator 一起提供 I reproduce the code below for completeness:为了完整起见,我重现了下面的代码:

/*
 *  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;
    }
}

It seems kind of painful to implement, and unfortunately, as seems to often be the case with advanced Mybatis features, the only doc is really the example checked into the git repo.实现起来似乎有点痛苦,不幸的是,高级Mybatis功能似乎经常出现这种情况,唯一的文档实际上是检入git repo 的示例。

You may want to look at using the SQL Builder class built in to Mybatis , where you could use the WHERE method and specify ILIKE in the argument, although I know that may be a bridge too far given the current usage of the generator code.您可能想看看使用内置于MybatisSQL Builder类,您可以在其中使用WHERE方法并在参数中指定ILIKE ,尽管我知道考虑到生成器代码的当前使用情况,这可能是一个桥梁。

There is a mybatis generator plugin org.mybatis.generator.plugins.CaseInsensitiveLikePlugin有一个 mybatis 生成器插件org.mybatis.generator.plugins.CaseInsensitiveLikePlugin

This plugin adds methods to the Example class (actually to the Criteria inner class) to support case insensitive LIKE searches该插件向 Example 类(实际上是 Criteria 内部类)添加方法以支持不区分大小写的 LIKE 搜索

You can use insensitive like 'XXXX', it can work with any database您可以使用不敏感的“XXXX”,它可以与任何数据库一起使用

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

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