代码之家  ›  专栏  ›  技术社区  ›  Maurice

在SQL查询中使用“true”而不是“true”会产生意外的结果

  •  0
  • Maurice  · 技术社区  · 7 年前

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

    我为columnname获取布尔字段为true的任何对象的id号 plantClimbs frostresistant spicy

    我创建的方法生成一个查询字符串,当plantclimps为true时,该字符串如下所示

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

    当我运行这个查询时,我看到一些意外的结果。它不是检索攀缘植物字段为true的所有种子记录id,而是获取攀缘植物字段为false且抗寒或辛辣字段恰好为true的种子记录的所有id。

    当我删除'true周围的字符时,它又开始获取正确的id's。我的问题是:为什么会这样?为什么把“真”放在一边似乎否定了一切,以至于攀缘植物场是假的种子记录反而被取走了?

    以下是我的完整方法:

    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;
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Nick SamSmith1986    7 年前

    因为你的 climbingPlant 列是布尔值,所以MySQL必须转换 'true' 与之比较的布尔值,这是(并且对于任何字符串)false。所以当你有 true 在引号中,它匹配 攀援植物 什么时候 攀援植物 是假的。其他列的值不相关。对于演示,请尝试以下操作:

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

    输出:

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