【问题标题】:Using 'true' as opposed to true in an SQL query gives unexpected results在 SQL 查询中使用 'true' 而不是 true 会产生意想不到的结果
【发布时间】:2019-01-18 01:20:41
【问题描述】:

我在使用 entityManager 对象运行 jpql 查询时发现了一些奇怪的东西。

对于列名 plantClimbs frostresistantspicy 的布尔字段为真的任何对象,我都会获取其 ID 号

当plantClimbs 为真时,我所做的方法会生成一个如下所示的查询字符串

select u.id from SeedRecord u WHERE u.climbingPlant = 'true' 

当我运行这个查询时,我看到了一些意想不到的结果。它不是检索所有的 SeedRecord id,其 crawlPlant 字段为真,而是获取所有的 seedrecord 的 id,其 crawlPlant 字段为假,并且frostResistant 或 Spicy 字段恰好为真。

当我删除 true 周围的 ' 字符时,它开始再次获取正确的 id。我的问题是:为什么会这样?为什么将 ' 放在 true 周围似乎会否定一切,从而实际上获取了 crawlPLant 字段为 false 的种子记录?

这是我的完整方法:

private Set<Long> findAllSeedRecordsByKeywordsOrBooleans(Set<String> checkKeywords, boolean plantClimbs, boolean teaPlant, boolean spicy){
    if (checkKeywords.isEmpty()
            && !plantClimbs
            && !spicy
            && !teaPlant) return Collections.EMPTY_SET;
    Set<String> availablePlantTypes = new HashSet<>();
    Set<String> availableProduceTypes = new HashSet<>();
    log.info("fetching entitymanager");
    EntityManager entityManager = seedRecordDao.getEntityManager();
    Map<String,Set<String>> containsProduceNameKeyword = new HashMap<>();
    Map<String,Set<PlantType>> containsPlantTypeKeyword = new HashMap<>();
    Map<String,Set<ProduceType>> containsProduceTypeKeyword = new HashMap<>();
    Set<String> searchProduceNames = new HashSet<>();
    Set<PlantType> searchPlantTypes = new HashSet<>();
    Set<ProduceType> searchProduceTypes = new HashSet<>();
    boolean hasPriorCondition = false;
    boolean produceNamesConditionApplied = false;
    boolean produceTypesConditionApplied = false;
    boolean plantTypesConditionApplied = false;

    StringBuilder filterQuery = new StringBuilder("select u.id from SeedRecord u WHERE ");
    if(!checkKeywords.isEmpty()) {
        log.info("getting the producenames");
        Set<String> availableProduceNames = seedRecordDao.getProduceNames()
                .stream().map(ProduceName::getProduceName).collect(Collectors.toSet());
        for (PlantType plantType : PlantType.values())
            availablePlantTypes.add(plantType.toString());
        for (ProduceType produceType : ProduceType.values())
            availableProduceTypes.add(produceType.toString());
        for (String keyword : checkKeywords) {
            if (availableProduceNames.contains(keyword)) {
                searchProduceNames.add(keyword);
                if (!produceNamesConditionApplied) {
                    if (!hasPriorCondition) {
                        filterQuery.append("u.produceName IN :produceNames ");
                        hasPriorCondition = true;
                    } else
                        filterQuery.append("OR u.produceName IN :produceNames ");
                    produceNamesConditionApplied = true;
                }
            } else if (availablePlantTypes.contains(keyword)) {
                searchPlantTypes.add(PlantType.valueOf(keyword));
                if (!plantTypesConditionApplied) {
                    if (!hasPriorCondition) {
                        filterQuery.append("u.plantType IN :plantTypes ");
                        hasPriorCondition = true;
                    } else
                        filterQuery.append("OR u.plantType IN :plantTypes ");
                    plantTypesConditionApplied = true;
                }
            } else if (availableProduceTypes.contains(keyword)) {
                searchProduceTypes.add(ProduceType.valueOf(keyword));
                if (!produceTypesConditionApplied) {
                    if (!hasPriorCondition) {
                        filterQuery.append("u.produceType IN :produceTypes ");
                        hasPriorCondition = true;
                    } else
                        filterQuery.append("OR u.produceType IN :produceTypes ");
                    produceTypesConditionApplied = true;
                }
            }
        }

        if (!searchProduceNames.isEmpty())
            containsProduceNameKeyword.put("produceNames", searchProduceNames);
        if (!searchProduceTypes.isEmpty())
            containsProduceTypeKeyword.put("produceTypes", searchProduceTypes);
        if (!searchPlantTypes.isEmpty())
            containsPlantTypeKeyword.put("plantTypes", searchPlantTypes);
    }

    if(plantClimbs)
        if (!hasPriorCondition) {
            filterQuery.append("u.climbingPlant = 'true' ");
            hasPriorCondition = true;
        }
        else
            filterQuery.append("OR u.climbingPlant = 'true' ");
    if(teaPlant)
        if (!hasPriorCondition) {
            filterQuery.append("u.teaPlant = 'true' ");
            hasPriorCondition = true;
        }
        else
            filterQuery.append("OR u.teaPlant = 'true' ");
    if(spicy)
        if (!hasPriorCondition) {
            filterQuery.append("u.spicy = 'true' ");
        }
        else
            filterQuery.append("OR u.spicy = 'true' ");
    try {
        log.info("preparing query");
        log.info(filterQuery.toString());
        TypedQuery<Long> query = entityManager.createQuery(filterQuery.toString(), Long.class);
        if (!containsProduceNameKeyword.isEmpty())
            containsProduceNameKeyword.forEach((parameter, input) -> query.setParameter(parameter, input));
        if (!containsPlantTypeKeyword.isEmpty())
            containsPlantTypeKeyword.forEach((parameter, input) -> query.setParameter(parameter, input));
        if (!containsProduceTypeKeyword.isEmpty())
            containsProduceTypeKeyword.forEach((parameter, input) -> query.setParameter(parameter, input));
        log.info("sending to database NOW");
        return new HashSet<>(query.getResultList());
    }
    catch(Exception e){
        throw e;
    }
}

【问题讨论】:

    标签: java mysql sql hibernate entitymanager


    【解决方案1】:

    这是因为您的 climbingPlant 列是布尔值,因此 MySQL 必须将 'true' 转换为布尔值才能与之进行比较,这(并且对于任何字符串)都是错误的。因此,当您在引号中添加 true 时,当 climbingPlant 为 false 时,它​​与 climbingPlant 匹配。其他列的值无关紧要。如需演示,请尝试以下操作:

    select 'true' = true, 'true' = false, 'anything' = false
    

    输出:

    'true' = true   'true' = false  'anything' = false  
    0               1               1
    

    【讨论】:

    • 我怀疑是这样的。谢谢你的回答,信息量很大
    • 不用担心。很高兴能帮上忙。
    猜你喜欢
    • 2021-06-27
    • 2017-10-11
    • 1970-01-01
    • 2017-03-19
    • 2021-10-04
    • 1970-01-01
    • 2019-04-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多